Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

745 lines
16 KiB

/******************************************************************************
Copyright (c) 1994 IBM Corporaion
wdvga.c
This module is a modification of the HAL display initialization and output
routines for IBM Woodfield WD90C24A Graphics system. This version of wdvga.c
is intended to be used by the OS loader to provide putc capabilities with
the WD card.
This file was created by copying s3vga.c and modifying it to remove
everything except the code that initializes the VGA common registers.
Author:
Hiroshi Itoh 25-Feb-1994
Revision History:
******************************************************************************/
#define USE_VGA_PALETTE 1
# include "halp.h"
# include "pvgaequ.h"
# include "wdvga.h"
/*****************************************************************************/
// +++++++ IBM BJB added PCI bus definitions and tab size definition
// PCI slot configuration space addresses
# define UPPER_PCI_SLOT 0x80804000L
# define LOWER_PCI_SLOT 0x80802000L
# define PCI_BASE UPPER_PCI_SLOT
// PCI configuration space record offsets
# define VENDOR_ID 0x00
# define DEVICE_ID 0x02
# define COMMAND 0X04
# define DEVICE_STATUS 0X06
# define REVISION_ID 0x08
# define PROG_INTERFACE 0x0a
# define BASE_MEM_ADDRESS 0x10
# define TAB_SIZE 4
/*****************************************************************************/
//
// Define forward referenced procedure prototypes.
//
VOID
InitializeWD (
VOID
);
BOOLEAN WDIsPresent (
VOID
);
VOID
SetWDVGAConfig (
VOID
);
VOID
LockPR (
USHORT,
PUCHAR
);
VOID
UnlockPR (
USHORT,
PUCHAR
);
VOID
RestorePR (
USHORT,
PUCHAR
);
//
// Define paradise registers setting variation
//
#define pr72_alt (pr72 | 0x8000) // avoid pr30 index conflict
#define pr1b_ual (pr1b) // pr1b unlock variation
#define pr1b_ush (pr1b | 0x4000) // pr1b unlock variation
#define pr1b_upr (pr1b | 0x8000) // pr1b unlock variation
//
// Define static data (in s3vga.c)
//
extern
ULONG
Row,
Column,
ScrollLine,
DisplayText;
/******************************************************************************
This routine initializes the WD display controller chip.
This is the initialization routine for WD90C24A2. This routine initializes
the WD90C24A2 chip in the sequence of VGA BIOS.
******************************************************************************/
VOID
InitializeWD( VOID )
{
ULONG DataLong;
USHORT i, j;
UCHAR DataByte;
UCHAR Index;
PVOID Index_3x4, Data_3x5;
ULONG MemBase;
// these lines were moved to here from the original jxdisp.c
// routine that called this one
//
// In the HAL, we just put the video card into text mode.
DisplayText = 25;
ScrollLine = 160;
// Enable Video Subsystem according to the WD90C24 reference book
WRITE_WD_UCHAR( SUBSYS_ENB, 0x16 );
WRITE_WD_UCHAR( Setup_OP, 0x01 );
WRITE_WD_UCHAR( SUBSYS_ENB, 0x0e );
WRITE_WD_UCHAR( VSub_EnB, VideoParam[0] );
SetWDVGAConfig();
// Note: Synchronous reset must be done before MISC_OUT write operation
WRITE_WD_UCHAR( Seq_Index, RESET ); // Synchronous Reset !
WRITE_WD_UCHAR( Seq_Data, 0x01 );
// For ATI card (0x63) we may want to change the frequence
WRITE_WD_UCHAR( MiscOutW, VideoParam[1] );
// Note: Synchronous reset must be done before CLOCKING MODE register is
// modified
WRITE_WD_UCHAR( Seq_Index, RESET ); // Synchronous Reset !
WRITE_WD_UCHAR( Seq_Data, 0x01 );
// Sequencer Register
for( Index = 1; Index < 5; Index++ )
{
WRITE_WD_UCHAR( Seq_Index, Index );
WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET + Index] );
}
// Set CRT Controller
// out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
// UnLockCR0_7();
WRITE_WD_UCHAR( WD_3D4_Index, VERTICAL_RETRACE_END );
DataByte = READ_WD_UCHAR( WD_3D5_Data );
DataByte = DataByte & 0x7f;
WRITE_WD_UCHAR( WD_3D5_Data, DataByte );
// CRTC controller CR0 - CR18
for( Index = 0; Index < 25; Index++ )
{
WRITE_WD_UCHAR( WD_3D4_Index, Index );
WRITE_WD_UCHAR( WD_3D5_Data, VideoParam[CRT_OFFSET + Index] );
}
// attribute write
// program palettes and mode register
for( Index = 0; Index < 21; Index++ )
{
WaitForVSync();
DataByte = READ_WD_UCHAR( Stat1_In ); // Initialize Attr. F/F
WRITE_WD_UCHAR( Attr_Index, Index );
// KeStallExecutionProcessor( 5 );
WRITE_WD_UCHAR( Attr_Data, VideoParam[ATTR_OFFSET + Index] );
// KeStallExecutionProcessor( 5 );
WRITE_WD_UCHAR( Attr_Index, 0x20 ); // Set into normal operation
}
WRITE_WD_UCHAR( Seq_Index, RESET ); // reset to normal operation !
WRITE_WD_UCHAR( Seq_Data, 0x03 );
// graphics controller
for( Index = 0; Index < 9; Index++ )
{
WRITE_WD_UCHAR( GC_Index, Index );
WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + Index] );
}
// turn off the text mode cursor
WRITE_WD_UCHAR( WD_3D4_Index, CURSOR_START );
WRITE_WD_UCHAR( WD_3D5_Data, 0x2D );
// Load character fonts into plane 2 (A0000-AFFFF)
WRITE_WD_UCHAR( Seq_Index, 0x02 ); // Enable Write Plane reg
WRITE_WD_UCHAR( Seq_Data, 0x04 ); // select plane 2
WRITE_WD_UCHAR( Seq_Index, 0x04 ); // Memory Mode Control reg
WRITE_WD_UCHAR( Seq_Data, 0x06 ); // access to all planes,
WRITE_WD_UCHAR( GC_Index, 0x05 ); // Graphic, Control Mode reg
WRITE_WD_UCHAR( GC_Data, 0x00 );
WRITE_WD_UCHAR( GC_Index, 0x06 );
WRITE_WD_UCHAR( GC_Data, 0x04 );
WRITE_WD_UCHAR( GC_Index, 0x04 );
WRITE_WD_UCHAR( GC_Data, 0x02 );
MemBase = 0xA0000; // Font Plane 2
for( i = 0; i < 256; i++ )
{
for( j = 0; j < 16; j++ )
{
WRITE_WD_VRAM( MemBase, VGAFont8x16[i * 16 + j] );
MemBase++;
}
// 32 bytes each character font
for( j = 16; j < 32; j++ )
{
WRITE_WD_VRAM( MemBase, 0 );
MemBase++;
}
}
// turn on screen
WRITE_WD_UCHAR( Seq_Index, 0x01 );
DataByte = READ_WD_UCHAR( Seq_Data );
DataByte &= 0xdf;
DataByte ^= 0x0;
WRITE_WD_UCHAR( Seq_Data, DataByte );
WaitForVSync();
// Enable all the planes through the DAC
WRITE_WD_UCHAR( DAC_Mask, 0xff );
for( i = 0; i < 768; i++ )
{
WRITE_WD_UCHAR( DAC_Data, ColorPalette[i] );
}
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// select plane 0, 1
WRITE_WD_UCHAR( Seq_Index, 0x02); // Enable Write Plane reg
WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET + 0x02] );
// access to planes 0, 1.
WRITE_WD_UCHAR( Seq_Index, 0x04); // Memory Mode Control reg
WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
WRITE_WD_UCHAR( GC_Index, 0x05 ); // Graphic, Control Mode reg
WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x05] );
WRITE_WD_UCHAR( GC_Index, 0x04);
WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x04] );
WRITE_WD_UCHAR( GC_Index, 0x06);
WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x06] );
//
// Set screen into blue
//
for( DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2 )
{
WRITE_WD_VRAM( DataLong, 0x20 );
#ifdef USE_VGA_PALETTE
WRITE_WD_VRAM( DataLong + 1, 0x07 );
#else
WRITE_WD_VRAM( DataLong + 1, 0x1F );
#endif
}
// End of initialize S3 standard VGA +3 mode
//
// Initialize the current display column, row, and ownership values.
//
Column = 0;
Row = 0;
return;
} /* end of InitializeWD() */
VOID
SetWDVGAConfig (
VOID
)
/*++
Routine Description:
Set WDVGA compatible configuration except DAC.
Arguments:
None.
Return Value:
None.
--*/
{
UCHAR SavePR5, SavePR10, SavePR11, SavePR20, SavePR72, Temp;
PUCHAR pPRtable;
LockPR( pr1b, NULL );
LockPR( pr30, NULL );
UnlockPR( pr20, NULL );
UnlockPR( pr10, &SavePR10 );
UnlockPR( pr11, &SavePR11 );
// non-ISO monitor setting clock
WRITE_WD_UCHAR( Seq_Index, CLOCKING_MODE );
Temp = READ_WD_UCHAR( Seq_Data );
WRITE_WD_UCHAR( Seq_Data, (Temp | 0x01));
Temp = READ_WD_UCHAR( MiscOutR );
WRITE_WD_UCHAR( MiscOutW, (Temp & 0xf3));
// other clocking chip selects
UnlockPR( pr72_alt, &SavePR72 );
WRITE_WD_UCHAR( Seq_Index, pr68 );
Temp = READ_WD_UCHAR( Seq_Data );
WRITE_WD_UCHAR( Seq_Data, ((Temp & 0xe7) | 0x08));
RestorePR( pr72_alt, &SavePR72 );
RestorePR( pr11, &SavePR11 );
RestorePR( pr10, &SavePR10 );
LockPR( pr20, NULL );
// start of WD90C24A2 both screen mode table
pPRtable = wd90c24a_both;
while (*pPRtable != END_PVGA) {
switch (*pPRtable++) {
case W_CRTC :
WRITE_WD_UCHAR( WD_3D4_Index, *pPRtable++ );
WRITE_WD_UCHAR( WD_3D5_Data, *pPRtable++ );
break;
case W_SEQ :
WRITE_WD_UCHAR( Seq_Index, *pPRtable++ );
WRITE_WD_UCHAR( Seq_Data, *pPRtable++ );
break;
case W_GCR :
WRITE_WD_UCHAR( GC_Index, *pPRtable++ );
WRITE_WD_UCHAR( GC_Data, *pPRtable++ );
break;
default :
break;
}
}
// unlock FLAT registers
UnlockPR( pr1b_ual, NULL );
WRITE_WD_UCHAR( WD_3D4_Index, pr19 );
WRITE_WD_UCHAR( WD_3D5_Data, ((pr19_s32 & 0xf3) | pr19_CENTER));
// lock FLAT registers
LockPR( pr1b, NULL );
#ifndef USE_VGA_PALETTE
// PR1/PR4 setting
UnlockPR( pr5, &SavePR5 );
WRITE_WD_UCHAR( GCR_Index, pr1 );
Temp = READ_WD_UCHAR( GCR_Data );
WRITE_WD_UCHAR( GCR_Data, (Temp | 0x30));
WRITE_WD_UCHAR( GCR_Index, pr4 );
Temp = READ_WD_UCHAR( GCR_Data );
WRITE_WD_UCHAR( GCR_Data, (Temp | 0x01));
RestorePR( pr5, &SavePR5 );
// PR16 setting
UnlockPR( pr10, &SavePR10 );
WRITE_WD_UCHAR( WD_3D4_Index, pr16 );
WRITE_WD_UCHAR( WD_3D5_Data, 0);
RestorePR( pr10, &SavePR10 );
// PR34a setting
UnlockPR( pr20, &SavePR20 );
WRITE_WD_UCHAR( Seq_Index, pr34a );
WRITE_WD_UCHAR( Seq_Data, 0x0f);
RestorePR( pr20, &SavePR20 );
#endif
} /* SetWDVGAConfig */
//
// Internal functions
//
VOID
LockPR (
USHORT PRnum,
PUCHAR pPRval
)
{
USHORT pIndex, pData;
UCHAR Index, Data;
switch (PRnum) {
case pr5:
pIndex = GC_Index;
pData = GC_Data;
Index = pr5;
Data = pr5_lock;
break;
case pr10:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr10;
Data = pr10_lock;
break;
case pr11:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr11;
Data = pr11_lock;
break;
case pr1b:
// case pr1b_ual:
// case pr1b_ush:
// case pr1b_upr:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr1b;
Data = pr1b_lock;
break;
case pr20:
pIndex = Seq_Index;
pData = Seq_Data;
Index = pr20;
Data = pr20_lock;
break;
case pr30:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr30;
Data = pr30_lock;
break;
case pr72_alt:
pIndex = Seq_Index;
pData = Seq_Data;
Index = pr72;
Data = pr72_lock;
break;
default:
return;
} /* endswitch */
WRITE_WD_UCHAR( pIndex, Index );
if (pPRval!=NULL) {
*pPRval = READ_WD_UCHAR( pData );
} /* endif */
WRITE_WD_UCHAR( pData, Data );
}
VOID
UnlockPR (
USHORT PRnum,
PUCHAR pPRval
)
{
USHORT pIndex, pData;
UCHAR Index, Data;
switch (PRnum) {
case pr5:
pIndex = GC_Index;
pData = GC_Data;
Index = pr5;
Data = pr5_unlock;
break;
case pr10:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr10;
Data = pr10_unlock;
break;
case pr11:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr11;
Data = pr11_unlock;
break;
// case pr1b:
case pr1b_ual:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr1b;
Data = pr1b_unlock;
break;
case pr1b_ush:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr1b;
Data = pr1b_unlock_shadow;
break;
case pr1b_upr:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr1b;
Data = pr1b_unlock_pr;
break;
case pr20:
pIndex = Seq_Index;
pData = Seq_Data;
Index = pr20;
Data = pr20_unlock;
break;
case pr30:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr30;
Data = pr30_unlock;
break;
case pr72_alt:
pIndex = Seq_Index;
pData = Seq_Data;
Index = pr72;
Data = pr72_unlock;
break;
default:
return;
} /* endswitch */
WRITE_WD_UCHAR( pIndex, Index );
if (pPRval!=NULL) {
*pPRval = READ_WD_UCHAR( pData );
} /* endif */
WRITE_WD_UCHAR( pData, Data );
}
VOID
RestorePR (
USHORT PRnum,
PUCHAR pPRval
)
{
USHORT pIndex, pData;
UCHAR Index, Data;
switch (PRnum) {
case pr5:
pIndex = GC_Index;
pData = GC_Data;
Index = pr5;
break;
case pr10:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr10;
break;
case pr11:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr11;
break;
case pr1b:
// case pr1b_ual:
// case pr1b_ush:
// case pr1b_upr:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr1b;
break;
case pr20:
pIndex = Seq_Index;
pData = Seq_Data;
Index = pr20;
break;
case pr30:
pIndex = WD_3D4_Index;
pData = WD_3D5_Data;
Index = pr30;
break;
case pr72_alt:
pIndex = Seq_Index;
pData = Seq_Data;
Index = pr72;
break;
default:
return;
} /* endswitch */
Data = *pPRval;
WRITE_WD_UCHAR( pIndex, Index );
WRITE_WD_UCHAR( pData, Data );
}
BOOLEAN
WDIsPresent (
VOID
)
/*++
Routine Description:
This routine returns TRUE if an WDVGA is present. It assumes that it's
already been established that a VGA is present. It performs the Western
Digital recommended ID test. If all this works, then this is indeed an
chip from Western Digital.
All the registers will be preserved either this function fails to find a
WD vga or a WD vga is found.
Arguments:
None.
Return Value:
TRUE if a WDVGA is present, FALSE if not.
--*/
{
UCHAR GraphSave0c;
UCHAR GraphSave0f;
UCHAR temp1,temp2;
BOOLEAN status = TRUE;
//
// write 3ce.0c
//
WRITE_WD_UCHAR( GC_Index, pr2 );
GraphSave0c = temp1 = READ_WD_UCHAR( GC_Data );
temp1 &= 0xbf;
WRITE_WD_UCHAR( GC_Data, temp1 );
//
// check 3ce.09 after lock
//
LockPR( pr5, &GraphSave0f ); // lock it
// WRITE_WD_UCHAR( GC_Index, pr5 );
// GraphSave0f = READ_WD_UCHAR( GC_Data );
// WRITE_WD_UCHAR( GC_Data, pr5_lock ); // lock it
WRITE_WD_UCHAR( GC_Index, pr0a );
temp1 = READ_WD_UCHAR( GC_Data );
WRITE_WD_UCHAR( GC_Data, (UCHAR)(temp1+1) );
temp2 = READ_WD_UCHAR( GC_Data );
WRITE_WD_UCHAR( GC_Data, temp1 );
if ((temp1+1) == temp2) {
status = FALSE;
goto NOT_WDVGA; // locked but writable
}
//
// check 3ce.09 after unlock
//
UnlockPR( pr5, NULL ); // lock it
// WRITE_WD_USHORT( GC_Index, (pr5_unlock*0x100+pr5) ); // unlock
WRITE_WD_UCHAR( GC_Index, pr0a );
temp1 = READ_WD_UCHAR( GC_Data );
WRITE_WD_UCHAR( GC_Data, (UCHAR)(temp1+1) );
temp2 = READ_WD_UCHAR( GC_Data );
WRITE_WD_UCHAR( GC_Data, temp1 );
if ((temp1+1) != temp2) {
status = FALSE;
goto NOT_WDVGA; // unlocked but not-writable
}
NOT_WDVGA:
//
// write 3ce.0c (post-process)
//
WRITE_WD_UCHAR( GC_Index, pr2 );
WRITE_WD_UCHAR( GC_Data, GraphSave0c);
RestorePR( pr5, &GraphSave0f );
// WRITE_WD_UCHAR( GC_Index, pr5 );
// WRITE_WD_UCHAR( GC_Data, GraphSave0f);
return status;
}
/*****************************************************************************/