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.
 
 
 
 
 
 

677 lines
20 KiB

/*++
Copyright (c) 1995 International Business Machines Corporation
Module Name:
pxs3.c
Abstract:
This module implements the HAL display initialization and output routines
for a PowerPC system using an S3 video adapter.
Author:
Jess Botts
Environment:
Kernel mode
Revision History:
--*/
#include "halp.h"
#include "pxs3.h"
#include "string.h"
#include "pxvgaequ.h"
//PHYSICAL ADDRESS of S3 video ram
#define S3_VIDEO_MEMORY_BASE 0xC0000000
VOID
HalpDisplayCharacterS3 (
IN UCHAR Character
);
VOID
HalpOutputCharacterS3 (
IN UCHAR AsciiChar
);
VOID
HalpDisplayPpcS3Setup (
VOID
);
// in pxdisp.c
VOID
WaitForVSync (
VOID
);
VOID
Scroll_Screen (
IN UCHAR line
);
extern ULONG HalpInitPhase;
extern PUCHAR HalpVideoMemoryBase;
extern PUCHAR HalpVideoCoprocBase;
extern ULONG HalpColumn;
extern ULONG HalpRow;
extern ULONG HalpHorizontalResolution;
extern ULONG HalpVerticalResolution;
extern USHORT HalpBytesPerRow;
extern USHORT HalpCharacterHeight;
extern USHORT HalpCharacterWidth;
extern ULONG HalpDisplayText;
extern ULONG HalpDisplayWidth;
extern ULONG HalpScrollLength;
extern ULONG HalpScrollLine;
extern BOOLEAN HalpDisplayOwnedByHal;
VOID
HalpDisplayPpcS3Setup (
VOID
)
/*++
Routine Description:
This routine initializes the S3 display controller chip.
Arguments:
None.
Return Value:
None.
--*/
{
//
// Routine Description:
//
// This is the initialization routine for S3 86C911. This routine initializes
// the S3 86C911 chip in the sequence of VGA BIOS for AT.
//
ULONG DataLong;
USHORT i,j;
UCHAR DataByte;
UCHAR Index;
// PVOID Index_3x4, Data_3x5;
ULONG MemBase;
PHYSICAL_ADDRESS physicalAddress;
if (HalpInitPhase == 0) {
HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(S3_VIDEO_MEMORY_BASE,
0x400000); // 4 MB
//
// IO control space has already been mapped in phase 1 via halpmapiospace
//
}
// Enable Video Subsystem
// Accordint to chapter 5.4.2 regular VGA setup sequence
// HalDisplayString(" Enable Video Subsystem...\n");
WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
// HalDisplayString(" Subsystem Enable = 0x10...\n");
WRITE_S3_UCHAR(Setup_OP, 0x01);
WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
WRITE_S3_UCHAR(DAC_Mask, 0x0); // Set screen into blank
WRITE_S3_UCHAR(Seq_Index, 0x01);
WRITE_S3_UCHAR(Seq_Data, 0x21);
//=========================================================================
//
// IBMBJB removed this section because it is not currently used, this
// was left commented out instead of deleting it in case we use
// a monochrome monitor in the future
//
// // Check monitor type to decide index address (currently not use)
// DataByte = READ_S3_UCHAR(MiscOutR);
// ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
//
// if (ColorMonitor) {
// Index_3x4 = (PVOID)S3_3D4_Index;
// Data_3x5 = (PVOID)S3_3D5_Data;
// } else {
// Index_3x4 = (PVOID)Mono_3B4;
// Data_3x5 = (PVOID)Mono_3B5;
// }
//
//=========================================================================
//
// -- Initialization Process Begin --
// According to appendix B-4 "ADVANCED PROGRAMMER'S GUIDE TO THE EGA/VGA"
// to set the default values to VGA +3 mode.
//
WRITE_S3_UCHAR(VSub_EnB,VideoParam[0]);
// Note: Synchronous reset must be done before MISC_OUT write operation
WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
WRITE_S3_UCHAR(Seq_Data, 0x01);
// For ATI card(0x63) we may want to change the frequence
WRITE_S3_UCHAR(MiscOutW,VideoParam[1]);
// Note: Synchronous reset must be done before CLOCKING MODE register is
// modified
WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
WRITE_S3_UCHAR(Seq_Data, 0x01);
// Sequencer Register
for (Index = 1; Index < 5; Index++) {
WRITE_S3_UCHAR(Seq_Index, Index);
WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+Index]);
}
#ifdef POLO // if compiling for a Polo
WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
DataByte = READ_S3_UCHAR(S3_3D5_Data);
if((DataByte & 0xf0) == 0xc0) { // if display adaptor is an S3 864
WRITE_S3_UCHAR(Seq_Index, 0x01);
DataByte = READ_S3_UCHAR(Seq_Data);
DataByte |= 0x01; // use an 8 dot character clock
WRITE_S3_UCHAR(Seq_Data, DataByte);
}
#endif
// Set CRT Controller
// out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
// UnLockCR0_7();
WRITE_S3_UCHAR(S3_3D4_Index, VERTICAL_RETRACE_END);
DataByte = READ_S3_UCHAR(S3_3D5_Data);
DataByte = DataByte & 0x7f;
WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
// CRTC controller CR0 - CR18
for (Index = 0; Index < 25; Index++) {
WRITE_S3_UCHAR(S3_3D4_Index, Index);
WRITE_S3_UCHAR(S3_3D5_Data, VideoParam[CRT_OFFSET+Index]);
}
// attribute write
// program palettes and mode register
// HalDisplayString(" Program palettes ...\n");
for (Index = 0; Index < 21; Index++) {
WaitForVSync();
DataByte = READ_S3_UCHAR(Stat1_In); // Initialize Attr. F/F
WRITE_S3_UCHAR(Attr_Index,Index);
KeStallExecutionProcessor(5);
WRITE_S3_UCHAR(Attr_Data,VideoParam[ATTR_OFFSET+Index]);
KeStallExecutionProcessor(5);
WRITE_S3_UCHAR(Attr_Index,0x20); // Set into normal operation
}
WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
WRITE_S3_UCHAR(Seq_Data, 0x03);
// graphics controller
// HalDisplayString(" Graphics controller...\n");
for (Index = 0; Index < 9; Index++) {
WRITE_S3_UCHAR(GC_Index, Index);
WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+Index]);
}
// turn off the text mode cursor
WRITE_S3_UCHAR(S3_3D4_Index, CURSOR_START);
WRITE_S3_UCHAR(S3_3D5_Data, 0x2D);
// Unlock S3 specific registers
WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
WRITE_S3_UCHAR(S3_3D5_Data, 0x48);
// Unlock S3 SC registers
WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
WRITE_S3_UCHAR(S3_3D5_Data, 0xa0);
// Disable enhanced mode
WRITE_S3_UCHAR(ADVFUNC_CNTL, 0x02);
// Turn off H/W Graphic Cursor
WRITE_S3_UCHAR(S3_3D4_Index, SC5);
WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
//=========================================================================
//
// IBMBJB S3 errata sheet says that CR40 can not be read correctly after
// power up until it has been written to, suggested workaround is
// to use the power on default (0xA4) Since the intent of the
// existing code was to reset bit 0, 0xA4 will be used to reset
// the bit. The other bits that are reset select the desired
// default configuration.
//
// If this register is written by the firmware then this fix is
// unneccessary. If future modifications of the firmware were to
// remove all writes to this register then this fix would have to
// be added here. This is being added now to protect this code
// from possible firmware changes.
//
// // Disable enhanced mode registers access
// WRITE_S3_UCHAR(S3_3D4_Index, SC0);
// DataByte = READ_S3_UCHAR(S3_3D5_Data);
// DataByte &= 0xfe;
// DataByte ^= 0x0;
//
// WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
//
WRITE_S3_UCHAR( S3_3D4_Index, SC0 );
WRITE_S3_UCHAR( S3_3D5_Data, 0xA4 );
//=========================================================================
// Set Misc 1 register
WRITE_S3_UCHAR(S3_3D4_Index, S3R0A);
DataByte = READ_S3_UCHAR(S3_3D5_Data);
DataByte &= 0xc7;
DataByte ^= 0x0;
WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
// Set S3R1 register
WRITE_S3_UCHAR(S3_3D4_Index, S3R1);
DataByte = READ_S3_UCHAR(S3_3D5_Data);
DataByte &= 0x80;
DataByte ^= 0x0;
WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
// Set S3R2 register
WRITE_S3_UCHAR(S3_3D4_Index, S3R2);
WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
// Set S3R4 register
WRITE_S3_UCHAR(S3_3D4_Index, S3R4);
DataByte = READ_S3_UCHAR(S3_3D5_Data);
DataByte &= 0xec;
DataByte ^= 0x0;
WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
//=========================================================================
//
// IBMBJB added this section to eliminate the DAC hardware cursor, this
// is done before setting registers 0x50 - 0x62 to default states
// so that R55's default state will not be undone.
//
// this sequence zeros the 2 least signifigant bits in command
// register 2 on the DAC
WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // set RS[3:2] to 10
DataByte = READ_S3_UCHAR( S3_3D5_Data );
DataByte &= 0xfc;
DataByte |= 0x02;
WRITE_S3_UCHAR( S3_3D5_Data, DataByte );
DataByte = READ_S3_UCHAR( DAC_Data );
DataByte &= 0xfc; // zero CR21,20 in DAC command
WRITE_S3_UCHAR( DAC_Data, DataByte ); // register 2
//=========================================================================
//
// IBMBJB Added code to configure for 18 bit color mode and reload the
// palette registers because the firmware configures for 24 bit
// color. If this is done when the system driver initializes for
// graphics mode then the text mode colors can not be changed
// properly.
WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // RS[3:2] = 01B to address
WRITE_S3_UCHAR( S3_3D5_Data, 0x01 ); // DAC command register 0
DataByte = READ_S3_UCHAR( DAC_Mask ); // reset bit 1 in DAC command
DataByte &= 0xfd; // register 0 to select 6 bit
WRITE_S3_UCHAR( DAC_Mask, DataByte ); // operation (18 bit color)
// IBMBJB added write to SDAC PLL control register to make sure CLK0
// is correct if we have to reinitialize after graphics mode
// initialization, this does not bother the 928/Bt485 card
// because the Bt485 DAC looks very much like the SDAC
WRITE_S3_UCHAR( DAC_WIndex, 0x0e ); // select SDAC PLL control reg
WRITE_S3_UCHAR( DAC_Data, 0x00 ); // select SDAC CLK0
WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // select DAC color palette
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 ); // registers
WRITE_S3_UCHAR( DAC_WIndex, 0 ); // start load in register 0
for( i = 0, j = 0; i < 256; ++i ) // load all color registers
{
WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // red intensity
WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // green intensity
WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // blue intensity
}
//=========================================================================
//
// IBMBJB added writes to registers 0x50 - 0x62 to set them to a known
// state because some of them are set by the firmware and are
// not correct for our use
//
// NOTE: there are some writes to the DAC registers in code that
// executes later that depend on R55[1:0] being 00B, if the
// default state of R55 is changed make sure that these bits
// are not changed
WRITE_S3_UCHAR( S3_3D4_Index, 0x50 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x51 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x52 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x53 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x54 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x55 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x56 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x57 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x58 );
#ifdef SAM_256
WRITE_S3_UCHAR( S3_3D5_Data, 0x40 );
#else
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
#endif
WRITE_S3_UCHAR( S3_3D4_Index, 0x59 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x5a );
WRITE_S3_UCHAR( S3_3D5_Data, 0x0a );
WRITE_S3_UCHAR( S3_3D4_Index, 0x5B );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x5C );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x5D );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x5E );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x5F );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
// IBMBJB changed value written from 0 to 1 for an S3 864 based card to
// clear up bad display caused by 864->SDAC FIFO underrun
WRITE_S3_UCHAR( S3_3D4_Index, 0x60 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x01 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x61 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
WRITE_S3_UCHAR( S3_3D4_Index, 0x62 );
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
//=========================================================================
//
// IBMBJB added setting bits 7 and 6 of CR65, errata sheet fix for split
// transfer problem in parallel and continuous addressing modes
// Note: side effect of setting bit 7 was a garbled firmware screen after
// shutdown.
// Set SR65 bits 7 and 6
WRITE_S3_UCHAR(S3_3D4_Index, 0x65);
DataByte = READ_S3_UCHAR(S3_3D5_Data);
DataByte |= 0x40;
// DataByte |= 0xc0;
WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
// Lock S3 SC registers
WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
// Lock S3 specific registers
WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
// Load character fonts into plane 2 (A0000-AFFFF)
// HalDisplayString(" Load Fonts into Plane2 ...\n");
WRITE_S3_UCHAR(Seq_Index,0x02); // Enable Write Plane reg
WRITE_S3_UCHAR(Seq_Data,0x04); // select plane 2
WRITE_S3_UCHAR(Seq_Index,0x04); // Memory Mode Control reg
WRITE_S3_UCHAR(Seq_Data,0x06); // access to all planes,
WRITE_S3_UCHAR(GC_Index,0x05); // Graphic, Control Mode reg
WRITE_S3_UCHAR(GC_Data,0x00);
WRITE_S3_UCHAR(GC_Index,0x06);
WRITE_S3_UCHAR(GC_Data,0x04);
WRITE_S3_UCHAR(GC_Index,0x04);
WRITE_S3_UCHAR(GC_Data,0x02);
MemBase = 0xA0000;
for (i = 0; i < 256; i++) {
for (j = 0; j < 16; j++) {
WRITE_S3_VRAM(MemBase, VGAFont8x16[i*16+j]);
MemBase++;
}
// 32 bytes each character font
for (j = 16; j < 32; j++) {
WRITE_S3_VRAM(MemBase, 0 );
MemBase++;
}
}
// turn on screen
WRITE_S3_UCHAR(Seq_Index, 0x01);
DataByte = READ_S3_UCHAR(Seq_Data);
DataByte &= 0xdf;
DataByte ^= 0x0;
WRITE_S3_UCHAR(Seq_Data, DataByte);
WaitForVSync();
// Enable all the planes through the DAC
WRITE_S3_UCHAR(DAC_Mask, 0xff);
// select plane 0, 1
WRITE_S3_UCHAR(Seq_Index, 0x02); // Enable Write Plane reg
WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x02]);
// access to planes 0, 1.
WRITE_S3_UCHAR(Seq_Index, 0x04); // Memory Mode Control reg
WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
WRITE_S3_UCHAR(GC_Index, 0x05); // Graphic, Control Mode reg
WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x05]);
WRITE_S3_UCHAR(GC_Index, 0x04);
WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x04]);
WRITE_S3_UCHAR(GC_Index, 0x06);
WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x06]);
//
// Set screen into blue
//
// HalDisplayString(" Set Screen into Blue ...\n");
for (DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2) {
WRITE_S3_VRAM(DataLong, 0x20);
WRITE_S3_VRAM(DataLong+1, 0x1F);
}
// End of initialize S3 standard VGA +3 mode
//
// Initialize the current display column, row, and ownership values.
//
HalpColumn = 0;
HalpRow = 0;
//IBMLAN===============================================================
// Added the following so that HalQueryDisplayParameters() and
// HalSetDisplayParameters() work with either S3 or P9.
HalpDisplayWidth = 80;
HalpDisplayText = 25;
HalpScrollLine = 160;
HalpScrollLength =
HalpScrollLine * (HalpDisplayText - 1);
//end IBMLAN===========================================================
HalpDisplayOwnedByHal = TRUE;
return;
} /* end of HalpDisplayPpcS3Setup() */
VOID
HalpDisplayCharacterS3 (
IN UCHAR Character
)
/*++
Routine Description:
This routine displays a character at the current x and y positions in
the frame buffer. If a newline is encounter, then the frame buffer is
scrolled. If characters extend below the end of line, then they are not
displayed.
Arguments:
Character - Supplies a character to be displayed.
Return Value:
None.
--*/
{
//
// If the character is a newline, then scroll the screen up, blank the
// bottom line, and reset the x position.
//
if (Character == '\n') {
HalpColumn = 0;
if (HalpRow < (HalpDisplayText - 1)) {
HalpRow += 1;
} else { // need to scroll up the screen
Scroll_Screen(1);
}
}
else if( Character == '\t' ) // tab?
{
HalpColumn += TAB_SIZE;
HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
if( HalpColumn >= HalpDisplayWidth ) // tab beyond end of screen?
{
HalpColumn = 0; // next tab stop is 1st column of next line
if( HalpRow >= (HalpDisplayText - 1) )
Scroll_Screen( 1 ); // scroll the screen up
else
++HalpRow;
}
}
else if (Character == '\r') {
HalpColumn = 0;
} else if (Character == 0x7f) { /* DEL character */
if (HalpColumn != 0) {
HalpColumn -= 1;
HalpOutputCharacterS3(0);
HalpColumn -= 1;
} else /* do nothing */
;
} else if (Character >= 0x20) {
// Auto wrap for 80 columns per line
if (HalpColumn >= HalpDisplayWidth) {
HalpColumn = 0;
if (HalpRow < (HalpDisplayText - 1)) {
HalpRow += 1;
} else { // need to scroll up the screen
Scroll_Screen(1);
}
}
HalpOutputCharacterS3(Character);
} else /* skip the nonprintable character */
;
return;
} /* end of HalpDisplayCharacterS3() */
VOID
HalpOutputCharacterS3 (
IN UCHAR AsciiChar
)
/*++
Routine Description:
This routine insert a set of pixels into the display at the current x
cursor position. If the x cursor position is at the end of the line,
then no pixels are inserted in the display.
Arguments:
Character - Supplies a character to be displayed.
Return Value:
None.
--*/
{
ULONG I;
//
// If the current x cursor position is within the current line, then insert
// the specified pixels into the last line of the text area and update the
// x cursor position.
//
if (HalpColumn < HalpDisplayWidth) {
I = (HalpRow*HalpScrollLine+HalpColumn*2);
WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
HalpColumn += 1;
} else // could expand to automatic wrap line. 9/9/92 By Andrew
;
return;
} /* end of HalpOutputCharacterS3() */