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

1412 lines
46 KiB

/************************************************************************/
/* */
/* INIT_M.C */
/* */
/* Sep 27 1993 (c) 1993, ATI Technologies Incorporated. */
/************************************************************************/
/********************** PolyTron RCS Utilities
$Revision: 1.16 $
$Date: 15 May 1996 16:35:42 $
$Author: RWolff $
$Log: S:/source/wnt/ms11/miniport/archive/init_m.c_v $
*
* Rev 1.16 15 May 1996 16:35:42 RWolff
* Waits for idle after setting accelerator mode.
*
* Rev 1.15 17 Apr 1996 13:09:26 RWolff
* Backed out Alpha LFB mapping as dense.
*
* Rev 1.14 11 Apr 1996 15:12:40 RWolff
* Now maps framebuffer as dense on DEC Alpha with PCI graphics card.
*
* Rev 1.13 31 Mar 1995 11:53:46 RWOLFF
* Changed from all-or-nothing debug print statements to thresholds
* depending on importance of the message.
*
* Rev 1.12 14 Feb 1995 15:41:20 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.11 03 Feb 1995 15:17:00 RWOLFF
* Added support for DCI, removed dead code.
*
* Rev 1.10 23 Dec 1994 10:47:18 ASHANMUG
* ALPHA/Chrontel-DAC
*
* Rev 1.9 22 Jul 1994 17:48:50 RWOLFF
* Merged with Richard's non-x86 code stream.
*
* Rev 1.8 27 Jun 1994 16:30:12 RWOLFF
* Now reports all hardware default mode tables as noninterlaced to
* avoid confusing the display applet.
*
* Rev 1.7 15 Jun 1994 11:07:08 RWOLFF
* Now uses VideoPortZeroDeviceMemory() to clear 24BPP screens on NT builds
* where this function is available.
*
* Rev 1.6 12 May 1994 11:05:32 RWOLFF
* Reports the refresh rate from the mode table, rather than always
* reporting "Use hardware default".
*
* Rev 1.5 31 Mar 1994 15:02:00 RWOLFF
* Added SetPowerManagement_m() function to implement DPMS handling.
*
* Rev 1.4 14 Mar 1994 16:31:36 RWOLFF
* XMillimeter field of mode information structure now set properly.
*
* Rev 1.3 03 Mar 1994 12:37:54 ASHANMUG
* Pageable
*
* Rev 1.1 31 Jan 1994 16:27:06 RWOLFF
* 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:40 RWOLFF
* Initial revision.
*
* Rev 1.6 24 Jan 1994 18:04:28 RWOLFF
* Now puts DAC in known state before setting video mode. This is to
* accomodate the Graphics Wonder (1M DRAM Mach 32 with BT48x DAC).
*
* Rev 1.5 14 Jan 1994 15:21:22 RWOLFF
* SetCurrentMode_m() and (new routine) ResetDevice_m() now initialize
* and deinitialize the bank manager.
*
* Rev 1.4 15 Dec 1993 15:26:48 RWOLFF
* Added note to clean up before sending to Microsoft.
*
* Rev 1.3 30 Nov 1993 18:16:34 RWOLFF
* MapVideoMemory_m() now sets memoryInformation->FrameBufferLength to
* aperture size rather than amount of video memory present.
*
* Rev 1.2 05 Nov 1993 13:25:24 RWOLFF
* Switched to defined values for memory type, 1280x1024 DAC initialization is
* now done in the same manner as for other resolutions.
*
* Rev 1.0 08 Oct 1993 11:20:34 RWOLFF
* Initial revision.
End of PolyTron RCS section *****************/
#ifdef DOC
INIT_M.C - Highest-level card-dependent routines for miniport.
DESCRIPTION
This file contains initialization and packet handling routines
for 8514/A-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 "amach.h"
#include "amach1.h"
#include "atimp.h"
#include "atint.h"
#define INCLUDE_INIT_M
#include "init_m.h"
#include "modes_m.h"
#include "services.h"
#include "setup_m.h"
/*
* Prototypes for static functions.
*/
static void QuerySingleMode_m(PVIDEO_MODE_INFORMATION ModeInformation, struct query_structure *QueryPtr, ULONG ModeIndex);
/*
* Allow miniport to be swapped out when not needed.
*/
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(PAGE_M, AlphaInit_m)
#pragma alloc_text(PAGE_M, Initialize_m)
#pragma alloc_text(PAGE_M, MapVideoMemory_m)
#pragma alloc_text(PAGE_M, QueryPublicAccessRanges_m)
#pragma alloc_text(PAGE_M, QueryCurrentMode_m)
#pragma alloc_text(PAGE_M, QueryAvailModes_m)
#pragma alloc_text(PAGE_M, QuerySingleMode_m)
#pragma alloc_text(PAGE_M, SetCurrentMode_m)
#pragma alloc_text(PAGE_M, ResetDevice_m)
#pragma alloc_text(PAGE_M, SetPowerManagement_m)
#pragma alloc_text(PAGE_M, ShareVideoMemory_m)
/* BankMap_m() can't be made pageable */
#endif
/***************************************************************************
*
* void AlphaInit_m(void);
*
* DESCRIPTION:
* Perform the initialization that would normally be done by the ROM
* BIOS on x86 machines.
*
* GLOBALS CHANGED:
* none
*
* CALLED BY:
* ATIMPFindAdapter()
*
* AUTHOR:
* Robert Wolff
*
* CHANGE HISTORY:
*
* TEST HISTORY:
*
***************************************************************************/
void AlphaInit_m(void)
{
OUTPW(MEM_CFG, 0);
DEC_DELAY
OUTPW(MISC_OPTIONS, 0xb0a9);
DEC_DELAY
OUTPW(MEM_BNDRY, 0);
DEC_DELAY
#if 0
OUTPW(CONFIG_STATUS_1, 0x1410);
DEC_DELAY
OUTPW(SCRATCH_PAD_1, 0);
DEC_DELAY
OUTPW(SCRATCH_PAD_0, 0);
DEC_DELAY
#endif
OUTPW(CLOCK_SEL, 0x250);
DEC_DELAY
OUTPW(DAC_W_INDEX, 0x40);
DEC_DELAY
OUTPW(MISC_CNTL, 0xC00);
DEC_DELAY
OUTPW(LOCAL_CONTROL, 0x1402);
#if defined (MIPS) || defined (_MIPS_)
DEC_DELAY
OUTPW(OVERSCAN_COLOR_8, 0); //RKE: to eliminate left overscan on MIPS
#endif
DEC_DELAY
return;
} /* AlphaInit_m() */
/***************************************************************************
*
* void Initialize_m(void);
*
* DESCRIPTION:
* This routine is the 8514/A-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_m(void)
{
/*
* Make sure we have enough available FIFO entries
* to initialize the card.
*/
CheckFIFOSpace_m(SIXTEEN_WORDS);
/*
* On the 68800, set the memory boundary to shared VGA memory.
* On all cards, set the screen and drawing engine to start
* at the beginning of accelerator memory and MEM_CNTL
* to linear.
*/
if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
OUTP (MEM_BNDRY,0);
OUTPW(CRT_OFFSET_LO, 0);
OUTPW(GE_OFFSET_LO, 0);
OUTPW(CRT_OFFSET_HI, 0);
OUTPW(GE_OFFSET_HI, 0);
OUTPW(MEM_CNTL,0x5006);
/*
* Reset the engine and FIFO, then return to normal operation.
*/
OUTPW(SUBSYS_CNTL,0x9000);
OUTPW(SUBSYS_CNTL,0x5000);
/*
* The hardware cursor is available only for Mach 32 cards.
* disable the cursor and initialize it to display quadrant I - 0
*/
if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
{
OUTPW(CURSOR_OFFSET_HI,0);
OUTPW(HORZ_CURSOR_OFFSET,0);
OUTP(VERT_CURSOR_OFFSET,0);
OUTPW(CURSOR_COLOR_0, 0x0FF00); /* Colour 0 black, colour 1 white */
OUTPW(EXT_CURSOR_COLOR_0,0); // black
OUTPW(EXT_CURSOR_COLOR_1,0xffff); // white
}
return;
} /* Initialize_m() */
/**************************************************************************
*
* VP_STATUS MapVideoMemory_m(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 Mach 32 card without linear framebuffer.
*
* CALLED BY:
* IOCTL_VIDEO_MAP_VIDEO_MEMORY packet of ATIMPStartIO()
*
* AUTHOR:
* Robert Wolff
*
* CHANGE HISTORY:
*
* TEST HISTORY:
*
***************************************************************************/
VP_STATUS MapVideoMemory_m(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 */
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.
* For our 8514/A-compatible cards, we always enable a 4M aperture
* if the LFB is available, so map the full 4M even if the
* aperture size is greater than the amount of video memory.
*/
memoryInformation->VideoRamLength = phwDeviceExtension->VideoRamSize;
memoryInformation->FrameBufferLength = 4 * ONE_MEG;
/*
* If the linear aperture is not available (==0), and we are
* dealing with a card which can use the VGA 64k aperture,
* map it in.
*/
if (QueryPtr->q_aperture_cfg == 0)
{
if ((phwDeviceExtension->ModelNumber == MACH32_ULTRA) &&
(QueryPtr->q_VGA_type == 1))
{
phwDeviceExtension->FrameLength = 0x10000;
phwDeviceExtension->PhysicalFrameAddress.LowPart = 0x0A0000;
memoryInformation->FrameBufferLength = phwDeviceExtension->FrameLength;
}
else{
/*
* This card can't use either linear or VGA aperture.
* Set frame buffer size to zero and return.
*/
memoryInformation->VideoRamBase = 0;
memoryInformation->FrameBufferLength = 0;
memoryInformation->FrameBufferBase = 0;
return NO_ERROR;
}
}
inIoSpace = 0;
#if 0 /* defined(ALPHA) if display driver can handle dense LFB */
if (QueryPtr->q_bus_type == BUS_PCI)
inIoSpace = 4;
#endif
status = VideoPortMapMemory(phwDeviceExtension,
phwDeviceExtension->PhysicalFrameAddress,
&(memoryInformation->FrameBufferLength),
&inIoSpace,
&(memoryInformation->VideoRamBase));
memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase;
return status;
} /* MapVideoMemory_m() */
/**************************************************************************
*
* VP_STATUS QueryPublicAccessRanges_m(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_m(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)) )
{
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 = 0x00000000;
// physicalPortLength = LINEDRAW+2 - physicalPortBase.LowPart;
physicalPortLength = 0x10000;
// *SANITIZE* If MM available, give MM ports instead.
return VideoPortMapMemory(phwDeviceExtension,
physicalPortBase,
&physicalPortLength,
&(portAccess->MappedInIoSpace),
&(portAccess->VirtualAddress));
} /* QueryPublicAccessRanges_m() */
/**************************************************************************
*
* VP_STATUS QueryCurrentMode_m(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_m(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)) )
{
return ERROR_INSUFFICIENT_BUFFER;
}
/*
* Fill in the mode information structure.
*/
ModeInformation = RequestPacket->OutputBuffer;
QuerySingleMode_m(ModeInformation, QueryPtr, phwDeviceExtension->ModeIndex);
return NO_ERROR;
} /* QueryCurrentMode_m() */
/**************************************************************************
*
* VP_STATUS QueryAvailModes_m(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_m(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)) )
{
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_m(ModeInformation, QueryPtr, CurrentMode);
return NO_ERROR;
} /* QueryCurrentMode_m() */
/**************************************************************************
*
* static void QuerySingleMode_m(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_m() and QueryAvailModes_m()
*
* AUTHOR:
* Robert Wolff
*
* CHANGE HISTORY:
*
* TEST HISTORY:
*
***************************************************************************/
static void QuerySingleMode_m(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 16:
ModeInformation->RedMask = 0x0000f800;
ModeInformation->GreenMask = 0x000007e0;
ModeInformation->BlueMask = 0x0000001f;
ModeInformation->NumberRedBits = 5;
ModeInformation->NumberGreenBits = 6;
ModeInformation->NumberBlueBits = 5;
CrtTable->ColourDepthInfo = PIX_WIDTH_16BPP | ORDER_16BPP_565;
break;
case 24:
/*
* Windows NT uses RGB as the standard 24BPP mode,
* so use this ordering for all DACs except the
* Brooktree 48x which only supports BGR.
*/
if (QueryPtr->q_DAC_type != DAC_BT48x)
{
ModeInformation->RedMask = 0x00ff0000;
ModeInformation->GreenMask = 0x0000ff00;
ModeInformation->BlueMask = 0x000000ff;
CrtTable->ColourDepthInfo = PIX_WIDTH_24BPP | ORDER_24BPP_RGB;
}
else{
ModeInformation->RedMask = 0x000000ff;
ModeInformation->GreenMask = 0x0000ff00;
ModeInformation->BlueMask = 0x00ff0000;
CrtTable->ColourDepthInfo = PIX_WIDTH_24BPP | ORDER_24BPP_BGR;
}
ModeInformation->NumberRedBits = 8;
ModeInformation->NumberGreenBits = 8;
ModeInformation->NumberBlueBits = 8;
break;
case 32:
/*
* Only the Brooktree 481 requires BGR,
* and it doesn't support 32BPP.
*/
ModeInformation->RedMask = 0xff000000;
ModeInformation->GreenMask = 0x00ff0000;
ModeInformation->BlueMask = 0x0000ff00;
ModeInformation->NumberRedBits = 8;
ModeInformation->NumberGreenBits = 8;
ModeInformation->NumberBlueBits = 8;
CrtTable->ColourDepthInfo = PIX_WIDTH_24BPP | ORDER_24BPP_RGBx;
break;
default:
ModeInformation->RedMask = 0x00000000;
ModeInformation->GreenMask = 0x00000000;
ModeInformation->BlueMask = 0x00000000;
ModeInformation->NumberRedBits = 6;
ModeInformation->NumberGreenBits = 6;
ModeInformation->NumberBlueBits = 6;
CrtTable->ColourDepthInfo = PIX_WIDTH_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;
}
/*
* Bit 4 of the m_disp_cntl field is set for interlaced and
* cleared for noninterlaced.
*
* 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 ((CrtTable->m_disp_cntl & 0x010) && (ModeInformation->Frequency != DEFAULT_REFRESH))
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() */
//
// When coming back from hibernate, mach32s can lock up and blackscreen.
// This is because the card itself has to be reinitialized.
// This initialization include at least the frame buffer initialization
// and the initialization of the use of memory mapped registers.
//
VOID
EnableMach32FrameBufferAndMemMappedRegisters(
PHW_DEVICE_EXTENSION pHwDeviceExtension
)
{
USHORT temp, temp1;
//
// enable the framebuffer.
//
temp = INPW(MEM_CFG) & 0x0fffc; /* Preserve bits 2-15 */
temp |= 0x0002; /* 4M aperture */
OUTPW(MEM_CFG, temp);
//
// enable memory mapped register use.
// save SRC_X ???
OUTPW(SRC_X, 0x0AAAA);
temp = INPW(R_SRC_X);
if (temp != 0x02AA)
VideoDebugPrint((DEBUG_NORMAL, "Can't use memory mapped ranges, read %x\n", temp));
temp1 = INPW(LOCAL_CONTROL);
temp1 |= 0x0020; // Enable memory mapped registers
OUTPW(LOCAL_CONTROL, temp1);
//restore SRC_X???: OUTPW(SRC_X, temp);
}
/**************************************************************************
*
* void SetCurrentMode_m(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.
*
* GLOBALS CHANGED:
* none
*
* CALLED BY:
* IOCTL_VIDEO_SET_CURRENT_MODE packet of ATIMPStartIO()
*
* AUTHOR:
* Robert Wolff
*
* CHANGE HISTORY:
* 1994 01 13 Added initialization of bank manager
*
* TEST HISTORY:
*
***************************************************************************/
void SetCurrentMode_m(struct query_structure *QueryPtr, struct st_mode_table *CrtTable)
{
WORD MiscOptions; /* Contents of MISC_OPTIONS register */
USHORT Scratch, USTemp; /* Temporary variable */
//
// When coming back from hibernate, mach32s can lock up and blackscreen.
// This is because the card itself has to be reinitialized.
// This initialization include at least the frame buffer initialization
// and the initialization of the use of memory mapped registers.
//
if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
{
// enable the framebuffer.
Scratch = INPW(MEM_CFG) & 0x0fffc; /* Preserve bits 2-15 */
Scratch |= 0x0002; /* 4M aperture */
OUTPW(MEM_CFG, Scratch);
// enable memory mapped register use.
// save SRC_X ???
OUTPW(SRC_X, 0x0AAAA);
Scratch = INPW(R_SRC_X);
if (Scratch != 0x02AA)
VideoDebugPrint((DEBUG_NORMAL, "Can't use memory mapped ranges, read %x\n", Scratch));
USTemp = INPW(LOCAL_CONTROL);
USTemp |= 0x0020; // Enable memory mapped registers
OUTPW(LOCAL_CONTROL, USTemp);
//restore SRC_X???: OUTPW(SRC_X, Scratch);
}
/*
* Put the DAC in a known state before we start.
*/
UninitTiDac_m();
Passth8514_m(SHOW_ACCEL); // turn vga pass through off
/*
* On cards with the "MISC_OPTIONS doesn't report video memory size
* correctly" bug, reset MISC_OPTIONS to show the true amount of
* video memory. This is done here rather than when we determine
* how much memory is present in order to avoid trashing the "blue
* screen" (no adverse effects on operation, but would generate
* large numbers of user complaints).
*/
if (((QueryPtr->q_asic_rev == CI_68800_6) || (QueryPtr->q_asic_rev == CI_68800_AX)) &&
(QueryPtr->q_VGA_type == 1) &&
((QueryPtr->q_memory_type == VMEM_DRAM_256Kx4) ||
(QueryPtr->q_memory_type == VMEM_DRAM_256Kx16) ||
(QueryPtr->q_memory_type == VMEM_DRAM_256Kx4_GRAP)))
{
MiscOptions = INPW(MISC_OPTIONS) & MEM_SIZE_STRIPPED;
switch (QueryPtr->q_memory_size)
{
case VRAM_512k:
MiscOptions |= MEM_SIZE_512K;
break;
case VRAM_1mb:
MiscOptions |= MEM_SIZE_1M;
break;
case VRAM_2mb:
MiscOptions |= MEM_SIZE_2M;
break;
case VRAM_4mb:
MiscOptions |= MEM_SIZE_4M;
break;
}
OUTPW(MISC_OPTIONS, MiscOptions);
}
setmode_m(CrtTable, (ULONG_PTR) &(phwDeviceExtension->RomBaseRange), (ULONG) phwDeviceExtension->ModelNumber);
/*
* On a Mach 8 card, 1280x1024 can only be done in split
* pixel mode. If we are running on a Mach 8, and this
* resolution was selected, go into split pixel mode.
*
* Bit 4 of EXT_GE_CONFIG is set for split pixel mode and
* clear for normal mode. Bit 3 must be set, since clearing
* it accesses EEPROM read/write mode.
*/
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA)
|| (phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA))
{
if (QueryPtr->q_desire_x == 1280)
OUTPW(EXT_GE_CONFIG, 0x0018);
else OUTPW(EXT_GE_CONFIG, 0x0008);
}
/*
* Default to 8 bits per pixel. Modes which require a different
* setting will change this in the init_ti_<depth>_m() function.
*/
OUTP(DAC_MASK, 0xff);
if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
{
switch (CrtTable->m_pixel_depth) // program the DAC for the
{ // other resolutions
case 4:
case 8:
InitTi_8_m((WORD)(CrtTable->ColourDepthInfo | 0x0a));
break;
case 16:
InitTi_16_m((WORD)(CrtTable->ColourDepthInfo | 0x0a), (ULONG_PTR) &(phwDeviceExtension->RomBaseRange)); /* 16 bit 565 */
break;
case 24:
case 32:
/*
* RGB/BGR and 24/32 bit mode information is
* stored in CrtTable->ColourDepthInfo.
*/
InitTi_24_m((WORD)(CrtTable->ColourDepthInfo | 0x0a), (ULONG_PTR) &(phwDeviceExtension->RomBaseRange));
break;
}
}
/*
* If we are going to be using the VGA aperture on a Mach 32,
* initialize the bank manager by saving the ATI extended register
* values and putting the VGA controller into packed pixel mode.
*
* We can't identify this case by looking at
* phwDeviceExtension->FrameLength because it is set to 0x10000
* when the VGA aperture is being used in the
* IOCTL_VIDEO_MAP_VIDEO_MEMORY packet which may or may not
* have been called by the time we reach this point.
*/
if ((phwDeviceExtension->ModelNumber == MACH32_ULTRA) &&
(QueryPtr->q_aperture_cfg == 0) &&
(QueryPtr->q_VGA_type == 1))
{
for (Scratch = 0; Scratch <= 2; Scratch++)
{
OUTP(reg1CE, (BYTE)(SavedExtRegs[Scratch] & 0x00FF));
SavedExtRegs[Scratch] = (SavedExtRegs[Scratch] & 0x00FF) | (INP(reg1CF) << 8);
}
OUTPW(HI_SEQ_ADDR, 0x0F02);
OUTPW(HI_SEQ_ADDR, 0x0A04);
OUTPW(reg3CE, 0x1000);
OUTPW(reg3CE, 0x0001);
OUTPW(reg3CE, 0x0002);
OUTPW(reg3CE, 0x0003);
OUTPW(reg3CE, 0x0004);
OUTPW(reg3CE, 0x0005);
OUTPW(reg3CE, 0x0506);
OUTPW(reg3CE, 0x0F07);
OUTPW(reg3CE, 0xFF08);
OUTPW(reg1CE, 0x28B0); /* Enable 256 colour, 1M video RAM */
OUTPW(reg1CE, 0x04B6); /* Select linear addressing */
OUTP(reg1CE, 0xBE);
OUTPW(reg1CE, (WORD)(((INP(reg1CF) & 0xF7) << 8) | 0xBE));
}
/*
* phwDeviceExtension->ReInitializing becomes TRUE in
* IOCTL_VIDEO_SET_COLOR_REGISTERS packet of ATIMPStartIO().
*
* If this is not the first time we are switching into graphics
* mode, set the palette to the last set of colours that was
* selected while in graphics mode.
*/
if (phwDeviceExtension->ReInitializing)
{
SetPalette_m(phwDeviceExtension->Clut,
phwDeviceExtension->FirstEntry,
phwDeviceExtension->NumEntries);
}
/*
* Clear visible screen.
*
* 24 and 32 BPP would require a q_desire_y value beyond the
* maximum allowable clipping value (1535) if we clear the screen
* using a normal blit. Since these pixel depths are only supported
* up to 800x600, we can fake it by doing a 16BPP blit of double the
* screen height, clipping the special case of 640x480 24BPP on
* a 1M card (this is the only true colour mode that will fit in
* 1M, so if we hit this case on a 1M card, we know which mode
* we're dealing with) to avoid running off the end of video memory.
*/
if (CrtTable->m_pixel_depth >= 24)
{
/*
* Save the colour depth configuration and switch into 16BPP
*/
Scratch = INPW(R_EXT_GE_CONFIG);
OUTPD(EXT_GE_CONFIG, (Scratch & 0xFFCF) | PIX_WIDTH_16BPP);
CheckFIFOSpace_m(SIXTEEN_WORDS);
OUTPW(DP_CONFIG, 0x2011);
OUTPW(ALU_FG_FN, 0x7); // Paint
OUTPW(FRGD_COLOR, 0); // Black
OUTPW(CUR_X, 0);
OUTPW(CUR_Y, 0);
OUTPW(DEST_X_START, 0);
OUTPW(DEST_X_END, QueryPtr->q_desire_x);
if (QueryPtr->q_memory_size == VRAM_1mb)
OUTPW(DEST_Y_END, 720); /* Only 640x480 24BPP will fit in 1M */
else
OUTPW(DEST_Y_END, (WORD)(2*(QueryPtr->q_desire_y)));
/*
* Let the blit finish then restore the colour depth configuration
*/
WaitForIdle_m();
OUTPD(EXT_GE_CONFIG, Scratch);
}
else{
/*
* Other colour depths can be handled by a normal blit, and the
* LFB may not be available, so use a blit to clear the screen.
*/
CheckFIFOSpace_m(SIXTEEN_WORDS);
OUTPW(DP_CONFIG, 0x2011);
OUTPW(ALU_FG_FN, 0x7); // Paint
OUTPW(FRGD_COLOR, 0); // Black
OUTPW(CUR_X, 0);
OUTPW(CUR_Y, 0);
OUTPW(DEST_X_START, 0);
OUTPW(DEST_X_END, QueryPtr->q_desire_x);
OUTPW(DEST_Y_END, QueryPtr->q_desire_y);
}
#if 0
/*
* In 800x600 24BPP, set the offset to start 1 pixel into video
* memory to avoid screen tearing. The MAP_VIDEO_MEMORY packet
* must adjust the framebuffer base to compensate for this.
*/
if ((QueryPtr->q_desire_x == 800) && (QueryPtr->q_pix_depth == 24))
{
OUTPW(CRT_OFFSET_LO, 3);
}
else
{
OUTPW(CRT_OFFSET_HI, 0);
}
#endif
WaitForIdle_m();
return;
} /* SetCurrentMode_m() */
/**************************************************************************
*
* void ResetDevice_m(void);
*
* DESCRIPTION:
* Reset the accelerator to allow the VGA miniport to switch
* into a VGA mode.
*
* GLOBALS CHANGED:
* none
*
* CALLED BY:
* IOCTL_VIDEO_RESET_DEVICE packet of ATIMPStartIO()
*
* AUTHOR:
* Robert Wolff
*
* CHANGE HISTORY:
*
* TEST HISTORY:
*
***************************************************************************/
void ResetDevice_m(void)
{
VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
/*
* If we are using the VGA aperture on a Mach 32, put its
* VGA controller into planar mode.
*/
if (phwDeviceExtension->FrameLength == 0x10000)
{
OUTPW(reg1CE, SavedExtRegs[0]);
OUTPW(reg1CE, SavedExtRegs[1]);
OUTPW(reg1CE, SavedExtRegs[2]);
OUTP(reg1CE, 0xBE);
OUTPW(reg1CE, (WORD)(((INP(reg1CF) & 0xF7) << 8) | 0xBE));
}
UninitTiDac_m();
Passth8514_m(SHOW_VGA);
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
Registers.Eax = 0x0003; // set text mode 3
VideoPortInt10(phwDeviceExtension, &Registers);
} /* ResetDevice_m() */
/**************************************************************************
*
* VP_STATUS SetPowerManagement_m(QueryPtr, DpmsState);
*
* struct query_structure *QueryPtr; Query information for the card
* 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_m(struct query_structure *QueryPtr, DWORD DpmsState)
{
struct st_mode_table *CrtTable; /* Mode table, used to obtain sync values */
/*
* Only accept valid states.
*/
if ((DpmsState < VideoPowerOn) || (DpmsState > VideoPowerOff))
return ERROR_INVALID_PARAMETER;
/*
* Set CrtTable to point to the mode table associated with the
* selected mode.
*
* When a pointer to a structure is incremented by an integer,
* the integer represents the number of structure-sized blocks
* to skip over, not the number of bytes to skip over.
*/
CrtTable = (struct st_mode_table *)QueryPtr;
((struct query_structure *)CrtTable)++;
CrtTable += phwDeviceExtension->ModeIndex;
SavedDPMSState = DpmsState;
/*
* Mach 32 rev. 6 and later supports turning the sync signals on and off
* through the HORZ_OVERSCAN registers, but some chips that report as
* rev. 6 don't have this implemented. Also, Mach 32 rev. 3 and Mach 8
* don't support this mechanism.
*
* Disabling the sync by setting it to start after the total will work
* for all chips. Most chips will de-synchronize if the sync is set
* to 1 more than the total, but some need higher values. To be sure
* of de-synchronizing, set the disabled sync signal to start at
* the highest possible value.
*/
switch (DpmsState)
{
case VideoPowerOn:
OUTP(H_SYNC_STRT, CrtTable->m_h_sync_strt);
OUTPW(V_SYNC_STRT, CrtTable->m_v_sync_strt);
break;
case VideoPowerStandBy:
OUTP(H_SYNC_STRT, 0xFF);
OUTPW(V_SYNC_STRT, CrtTable->m_v_sync_strt);
break;
case VideoPowerSuspend:
OUTP(H_SYNC_STRT, CrtTable->m_h_sync_strt);
OUTPW(V_SYNC_STRT, 0x0FFF);
break;
case VideoPowerOff:
OUTP(H_SYNC_STRT, 0xFF);
OUTPW(V_SYNC_STRT, 0x0FFF);
break;
/*
* This case should never happen, because the initial
* acceptance of only valid states should have already
* rejected anything that will appear here.
*/
default:
break;
}
return NO_ERROR;
} /* SetPowerManagement_m() */
DWORD GetPowerManagement_m(PHW_DEVICE_EXTENSION phwDeviceExtension)
/*
* DESCRIPTION:
* Report which DPMS state we are in.
*
* PARAMETERS:
* phwDeviceExtension Points to per-adapter device extension.
*
* RETURN VALUE:
* Current DPMS state (VIDEO_POWER_STATE enumeration).
*/
{
ASSERT(phwDeviceExtension != NULL);
/*
* On the Mach 8, the sync start registers are write-only, so
* we can't check which state we are in. For this reason, we
* have saved the state we switched into using SetPowerManagement_m().
* On the Mach 32, we can either use this saved state or read
* the sync start registers, but using the same method as for
* the Mach 8 reduces complexity.
*/
return SavedDPMSState;
} /* GetPowerManagement_m() */
/**************************************************************************
*
* VP_STATUS ShareVideoMemory_m(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_m(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 */
/*
* We can only share the aperture with application programs if there
* is an aperture available. If both the LFB and the on-board VGA
* and therefore the VGA aperture) are disabled, report that we
* can't share the aperture.
*/
if ((QueryPtr->q_aperture_cfg == 0) && (QueryPtr->q_VGA_type == 0))
return ERROR_INVALID_FUNCTION;
InputPtr = RequestPacket->InputBuffer;
if ((InputPtr->ViewOffset > phwDeviceExtension->VideoRamSize) ||
((InputPtr->ViewOffset + InputPtr->ViewSize) > phwDeviceExtension->VideoRamSize))
{
VideoDebugPrint((DEBUG_ERROR, "ShareVideoMemory_m() - 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 1M boundary (4M boundary for 4M
* 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, /* 64k VGA aperture */
FALSE, /* No separate read/write banks */
BankMap_m, /* 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_m() */
/**************************************************************************
*
* void BankMap_m(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_m(ULONG BankRead, ULONG BankWrite, PVOID Context)
{
OUTPW( reg1CE, (USHORT)(((BankWrite & 0x0f) << 9) | 0xb2));
OUTPW( reg1CE, (USHORT)(((BankWrite & 0x30) << 4) | 0xae));
return;
} /* BankMap_m() */