mirror of https://github.com/lianthony/NT4.0
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.
938 lines
21 KiB
938 lines
21 KiB
/*++
|
|
|
|
Copyright (c) 1995 International Business Machines Corporation
|
|
|
|
Module Name:
|
|
|
|
pxwd.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the HAL display initialization and output routines
|
|
for a PowerPC system using a Western Digital video adapter.
|
|
|
|
Author:
|
|
|
|
Jim Wooldridge
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "halp.h"
|
|
#include "pxwd.h"
|
|
#include "string.h"
|
|
//#include "txtpalet.h"
|
|
#include "pci.h"
|
|
|
|
//
|
|
// Data Types used only in this file
|
|
//
|
|
|
|
typedef enum _LCD_TYPE{
|
|
NOT_CHECKED = 0x00, // panel type has not been checked yet
|
|
NoLCD = 0x01, // CRT
|
|
IBM_F8515 = 0x02, // CRT + IBM F8515 10.4" TFT LCD
|
|
IBM_F8532 = 0x04, // CRT + IBM F8532 10.4" TFT SVGA LCD
|
|
TOSHIBA_DSTNC = 0x08, // CRT + Toshiba 10.4" Dual Scan STN Color LCD
|
|
UNKNOWN_LCD = 0x80 // panel not recognized
|
|
} LCD_TYPE;
|
|
|
|
typedef struct{
|
|
LCD_TYPE Type;
|
|
ULONG XResolution;
|
|
ULONG YResolution;
|
|
} PANEL_REC;
|
|
|
|
extern PUCHAR HalpVideoMemoryBase;
|
|
|
|
extern BOOLEAN HalpDisplayOwnedByHal;
|
|
|
|
extern ULONG HalpInitPhase;
|
|
|
|
//
|
|
// Define OEM font variables.
|
|
//
|
|
|
|
extern USHORT HalpBytesPerRow;
|
|
extern USHORT HalpCharacterHeight;
|
|
extern USHORT HalpCharacterWidth;
|
|
extern ULONG HalpDisplayText;
|
|
extern ULONG HalpDisplayWidth;
|
|
extern ULONG HalpScrollLength;
|
|
extern ULONG HalpScrollLine;
|
|
|
|
//
|
|
// Define display variables.
|
|
//
|
|
|
|
extern ULONG HalpColumn;
|
|
extern ULONG HalpRow;
|
|
extern ULONG HalpHorizontalResolution;
|
|
extern ULONG HalpVerticalResolution;
|
|
|
|
|
|
//
|
|
// Prototypes
|
|
//
|
|
|
|
VOID
|
|
GetPanelType(),
|
|
TurnOnLCD( BOOLEAN );
|
|
|
|
extern VOID WaitForVSync();
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
|
|
PANEL_REC
|
|
LCDPanel = {NOT_CHECKED, 0, 0};
|
|
|
|
//
|
|
// Western Digital internal functions
|
|
//
|
|
|
|
static VOID
|
|
LockPR (
|
|
USHORT PRnum,
|
|
PUCHAR pPRval
|
|
)
|
|
{
|
|
USHORT pIndex, pData;
|
|
UCHAR Index, Data;
|
|
switch (PRnum) {
|
|
case pr5:
|
|
pIndex = PORT_GCR_INDEX;
|
|
pData = PORT_GCR_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 = PORT_SEQ_INDEX;
|
|
pData = PORT_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 = PORT_SEQ_INDEX;
|
|
pData = PORT_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 );
|
|
}
|
|
|
|
static VOID
|
|
UnlockPR (
|
|
USHORT PRnum,
|
|
PUCHAR pPRval
|
|
)
|
|
{
|
|
USHORT pIndex, pData;
|
|
UCHAR Index, Data;
|
|
switch (PRnum) {
|
|
case pr5:
|
|
pIndex = PORT_GCR_INDEX;
|
|
pData = PORT_GCR_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 = PORT_SEQ_INDEX;
|
|
pData = PORT_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 = PORT_SEQ_INDEX;
|
|
pData = PORT_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 );
|
|
|
|
}
|
|
static VOID
|
|
RestorePR (
|
|
USHORT PRnum,
|
|
PUCHAR pPRval
|
|
)
|
|
{
|
|
USHORT pIndex, pData;
|
|
UCHAR Index, Data;
|
|
switch (PRnum) {
|
|
case pr5:
|
|
pIndex = PORT_GCR_INDEX;
|
|
pData = PORT_GCR_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 = PORT_SEQ_INDEX;
|
|
pData = PORT_SEQ_DATA;
|
|
Index = pr20;
|
|
break;
|
|
case pr30:
|
|
pIndex = WD_3D4_Index;
|
|
pData = WD_3D5_Data;
|
|
Index = pr30;
|
|
break;
|
|
case pr72_alt:
|
|
pIndex = PORT_SEQ_INDEX;
|
|
pData = PORT_SEQ_DATA;
|
|
Index = pr72;
|
|
break;
|
|
default:
|
|
return;
|
|
} /* endswitch */
|
|
|
|
Data = *pPRval;
|
|
WRITE_WD_UCHAR( pIndex, Index );
|
|
WRITE_WD_UCHAR( pData, Data );
|
|
|
|
}
|
|
|
|
static 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( PORT_SEQ_INDEX, CLOCKING_MODE );
|
|
Temp = READ_WD_UCHAR( PORT_SEQ_DATA );
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, (Temp | 0x01));
|
|
|
|
Temp = READ_WD_UCHAR( PORT_GEN_MISC_RD );
|
|
WRITE_WD_UCHAR( PORT_GEN_MISC_WR, (Temp & 0xf3));
|
|
|
|
// other clocking chip selects
|
|
UnlockPR( pr72_alt, &SavePR72 );
|
|
|
|
RestorePR( pr72_alt, &SavePR72 );
|
|
|
|
RestorePR( pr11, &SavePR11 );
|
|
RestorePR( pr10, &SavePR10 );
|
|
LockPR( pr20, NULL );
|
|
|
|
// start of WD90C24A2 both screen mode table
|
|
|
|
if( LCDPanel.Type == IBM_F8532 )
|
|
pPRtable = wd90c24a_both_800;
|
|
else
|
|
pPRtable = wd90c24a_both_640;
|
|
|
|
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( PORT_SEQ_INDEX, *pPRtable++ );
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, *pPRtable++ );
|
|
break;
|
|
case W_GCR :
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, *pPRtable++ );
|
|
WRITE_WD_UCHAR( PORT_GCR_DATA, *pPRtable++ );
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
|
|
// unlock FLAT registers
|
|
|
|
UnlockPR( pr1b_ual, NULL );
|
|
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, pr68 );
|
|
Temp = READ_WD_UCHAR( PORT_SEQ_DATA );
|
|
|
|
if( LCDPanel.Type == IBM_F8532 )
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, ((Temp & 0xe7) | 0x10) );
|
|
else
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, ((Temp & 0xe7) | 0x08) );
|
|
|
|
WRITE_WD_UCHAR( WD_3D4_Index, pr19 );
|
|
|
|
if( LCDPanel.Type == IBM_F8532 )
|
|
WRITE_WD_UCHAR( WD_3D5_Data, (pr19_s32 & 0xf3));
|
|
else
|
|
WRITE_WD_UCHAR( WD_3D5_Data, (pr19_s32 & 0xf3));
|
|
|
|
// lock FLAT registers
|
|
|
|
LockPR( pr1b, NULL );
|
|
|
|
} /* SetWDVGAConfig */
|
|
|
|
VOID
|
|
HalpDisplayPpcWDSetup (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine initializes the Western Digital display controller chip.
|
|
|
|
Arguments:
|
|
None.
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
ULONG DataLong, stop;
|
|
USHORT i, j;
|
|
UCHAR DataByte;
|
|
UCHAR Index;
|
|
PVOID Index_3x4, Data_3x5;
|
|
ULONG MemBase;
|
|
PHYSICAL_ADDRESS physicalAddress;
|
|
|
|
if (HalpInitPhase == 0) {
|
|
|
|
HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
|
|
0x400000); // 4 MB
|
|
} else {
|
|
|
|
//
|
|
// Map video memory space via pte's
|
|
//
|
|
|
|
physicalAddress.HighPart = 0;
|
|
physicalAddress.LowPart = PCI_MEMORY_PHYSICAL_BASE ;
|
|
HalpVideoMemoryBase = MmMapIoSpace(physicalAddress,
|
|
0x400000,
|
|
FALSE);
|
|
|
|
//
|
|
// IO control space has already been mapped in phase 1 via halpmapiospace
|
|
//
|
|
|
|
}
|
|
|
|
if( LCDPanel.Type == NOT_CHECKED )
|
|
GetPanelType();
|
|
|
|
// turn the panel off before configuring it (prevents blowing the fuse)
|
|
|
|
TurnOnLCD( FALSE );
|
|
|
|
// 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( PORT_SYS_VGA_ENABLE, VideoParam[0] );
|
|
|
|
SetWDVGAConfig();
|
|
|
|
// turn off the hardware cursor
|
|
|
|
WRITE_WD_USHORT( EPR_INDEX, 0x1002 );
|
|
WRITE_WD_USHORT( EPR_DATA, 0x0000 );
|
|
|
|
// Note: Synchronous reset must be done before MISC_OUT write operation
|
|
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // Synchronous Reset !
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x01 );
|
|
|
|
// For ATI card (0x63) we may want to change the frequence
|
|
|
|
if( LCDPanel.Type == IBM_F8532 )
|
|
WRITE_WD_UCHAR( PORT_GEN_MISC_WR, (VideoParam[1] & 0xf3) );
|
|
else
|
|
WRITE_WD_UCHAR( PORT_GEN_MISC_WR, VideoParam[1] );
|
|
|
|
// Note: Synchronous reset must be done before CLOCKING MODE register is
|
|
// modified
|
|
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // Synchronous Reset !
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x01 );
|
|
|
|
// Sequencer Register
|
|
|
|
for( Index = 1; Index < 5; Index++ )
|
|
{
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, Index );
|
|
WRITE_WD_UCHAR( PORT_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 );
|
|
|
|
if( LCDPanel.Type == IBM_F8532 )
|
|
WRITE_WD_UCHAR( WD_3D5_Data, CRTC_800x600x60_Text[Index] );
|
|
else
|
|
WRITE_WD_UCHAR( WD_3D5_Data, CRTC_640x480x60_Text[Index] );
|
|
}
|
|
|
|
// attribute write
|
|
// program palettes and mode register
|
|
|
|
for( Index = 0; Index < 21; Index++ )
|
|
{
|
|
WaitForVSync();
|
|
DataByte = READ_WD_UCHAR( PORT_GEN_FEATURE_WR_C ); // Initialize Attr. F/F
|
|
WRITE_WD_UCHAR( PORT_ATTR_DATA_WR, Index );
|
|
|
|
// KeStallExecutionProcessor( 5 );
|
|
WRITE_WD_UCHAR( PORT_ATTR_INDEX, VideoParam[ATTR_OFFSET + Index] );
|
|
|
|
// KeStallExecutionProcessor( 5 );
|
|
WRITE_WD_UCHAR( PORT_ATTR_DATA_WR, 0x20 ); // Set into normal operation
|
|
}
|
|
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // reset to normal operation !
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x03 );
|
|
|
|
// graphics controller
|
|
|
|
for( Index = 0; Index < 9; Index++ )
|
|
{
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, Index );
|
|
WRITE_WD_UCHAR( PORT_GCR_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( PORT_SEQ_INDEX, 0x02 ); // Enable Write Plane reg
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x04 ); // select plane 2
|
|
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x04 ); // Memory Mode Control reg
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x06 ); // access to all planes,
|
|
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x05 ); // Graphic, Control Mode reg
|
|
WRITE_WD_UCHAR( PORT_GCR_DATA, 0x00 );
|
|
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x06 );
|
|
WRITE_WD_UCHAR( PORT_GCR_DATA, 0x04 );
|
|
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x04 );
|
|
WRITE_WD_UCHAR( PORT_GCR_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( PORT_SEQ_INDEX, 0x01 );
|
|
DataByte = READ_WD_UCHAR( PORT_SEQ_DATA );
|
|
DataByte &= 0xdf;
|
|
DataByte ^= 0x0;
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, DataByte );
|
|
|
|
WaitForVSync();
|
|
|
|
// Enable all the planes through the DAC
|
|
WRITE_WD_UCHAR( PORT_DAC_PIX_MASK, 0xff );
|
|
|
|
// start loading palette in register 0
|
|
WRITE_WD_UCHAR( PORT_DAC_WRITE_PIX_ADDR, 0 );
|
|
|
|
for( i = 0; i < 768; i++ )
|
|
{
|
|
WRITE_WD_UCHAR( PORT_DAC_DATA, TextPalette[i] );
|
|
}
|
|
|
|
//
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
// select plane 0, 1
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x02); // Enable Write Plane reg
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, VideoParam[SEQ_OFFSET + 0x02] );
|
|
|
|
// access to planes 0, 1.
|
|
WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x04); // Memory Mode Control reg
|
|
WRITE_WD_UCHAR( PORT_SEQ_DATA, VideoParam[SEQ_OFFSET+0x04]);
|
|
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x05 ); // Graphic, Control Mode reg
|
|
WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x05] );
|
|
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x04);
|
|
WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x04] );
|
|
|
|
WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x06);
|
|
WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x06] );
|
|
|
|
//
|
|
// Set screen into blue
|
|
//
|
|
|
|
if( LCDPanel.Type == IBM_F8532 )
|
|
stop = 0xb9db0;
|
|
else
|
|
stop = 0xb92c0;
|
|
|
|
for( DataLong = 0xB8000; DataLong < stop; DataLong += 2 )
|
|
{
|
|
WRITE_WD_VRAM( DataLong, 0x20 );
|
|
WRITE_WD_VRAM( DataLong + 1, 0x1F );
|
|
}
|
|
|
|
//
|
|
// turn the panel back on
|
|
//
|
|
|
|
TurnOnLCD( TRUE );
|
|
|
|
//
|
|
// 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.
|
|
|
|
if( LCDPanel.Type == IBM_F8532 )
|
|
{
|
|
HalpDisplayWidth = 100;
|
|
HalpDisplayText = 37;
|
|
HalpScrollLine = 200;
|
|
}
|
|
else
|
|
{
|
|
HalpDisplayWidth = 80;
|
|
HalpDisplayText = 25;
|
|
HalpScrollLine = 160;
|
|
}
|
|
|
|
HalpScrollLength =
|
|
HalpScrollLine * (HalpDisplayText - 1);
|
|
|
|
//end IBMLAN===========================================================
|
|
HalpDisplayOwnedByHal = TRUE;
|
|
|
|
return;
|
|
} /* end of InitializeWD() */
|
|
|
|
VOID
|
|
GetPanelType()
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine get the type of attached LCD display.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
UCHAR data8;
|
|
|
|
//
|
|
// read the panel controller
|
|
//
|
|
|
|
WRITE_WD_UCHAR(0xd00, 0xff);
|
|
data8 = READ_WD_UCHAR(0xd01);
|
|
|
|
switch (data8 & 0x0f) {
|
|
case 0x0e:
|
|
LCDPanel.Type = IBM_F8515;
|
|
LCDPanel.XResolution = 640;
|
|
LCDPanel.YResolution = 480;
|
|
break;
|
|
|
|
case 0x0c:
|
|
LCDPanel.Type = IBM_F8532;
|
|
LCDPanel.XResolution = 800;
|
|
LCDPanel.YResolution = 600;
|
|
break;
|
|
|
|
case 0x0d:
|
|
LCDPanel.Type = TOSHIBA_DSTNC;
|
|
LCDPanel.XResolution = 640;
|
|
LCDPanel.YResolution = 480;
|
|
break;
|
|
|
|
default:
|
|
LCDPanel.Type = UNKNOWN_LCD;
|
|
LCDPanel.XResolution = 0;
|
|
LCDPanel.YResolution = 0;
|
|
break;
|
|
}
|
|
|
|
} // end GetPanelType()
|
|
|
|
BOOLEAN
|
|
HalpPhase0EnablePmController()
|
|
|
|
{
|
|
|
|
ULONG i, BaseAddress;
|
|
USHORT VendorID, DeviceID, Command;
|
|
|
|
//
|
|
// Locates the controller on the PCI bus, and configures it
|
|
//
|
|
|
|
if (HalpPhase0MapBusConfigSpace() == FALSE){
|
|
|
|
return( FALSE );
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < PCI_MAX_DEVICES; i++) {
|
|
|
|
HalpPhase0GetPciDataByOffset(0,
|
|
i,
|
|
&VendorID,
|
|
FIELD_OFFSET(PCI_COMMON_CONFIG,VendorID),
|
|
sizeof(VendorID));
|
|
|
|
HalpPhase0GetPciDataByOffset(0,
|
|
i,
|
|
&DeviceID,
|
|
FIELD_OFFSET(PCI_COMMON_CONFIG,DeviceID),
|
|
sizeof(DeviceID));
|
|
|
|
if ((VendorID == 0x1014) && (DeviceID == 0x001C)) {
|
|
|
|
HalpPhase0GetPciDataByOffset(0,
|
|
i,
|
|
&Command,
|
|
FIELD_OFFSET(PCI_COMMON_CONFIG,Command),
|
|
sizeof(Command));
|
|
|
|
Command |= PCI_ENABLE_IO_SPACE;
|
|
BaseAddress = (ULONG)0x4100;
|
|
|
|
HalpPhase0SetPciDataByOffset(0,
|
|
i,
|
|
&Command,
|
|
FIELD_OFFSET(PCI_COMMON_CONFIG,Command),
|
|
sizeof(Command));
|
|
|
|
HalpPhase0SetPciDataByOffset(0,
|
|
i,
|
|
&BaseAddress,
|
|
FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.BaseAddresses[0]),
|
|
sizeof(BaseAddress));
|
|
|
|
break;
|
|
} /* endif */
|
|
|
|
} /* endfor */
|
|
|
|
} /* end if map config space succeeds */
|
|
|
|
HalpPhase0UnMapBusConfigSpace();
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
HalpPhase1EnablePmController()
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
PCI_SLOT_NUMBER slot;
|
|
PCI_COMMON_CONFIG PCIDeviceConfig;
|
|
|
|
slot.u.AsULONG = (ULONG)0;
|
|
|
|
//
|
|
// Locates the controller on the PCI bus, and configures it
|
|
//
|
|
|
|
for (i = 0; i < PCI_MAX_DEVICES; i++) {
|
|
|
|
slot.u.bits.DeviceNumber = i;
|
|
|
|
HalGetBusData (
|
|
PCIConfiguration,
|
|
0,
|
|
slot.u.AsULONG,
|
|
&PCIDeviceConfig,
|
|
sizeof (PCIDeviceConfig)
|
|
);
|
|
|
|
if ((PCIDeviceConfig.VendorID == 0x1014) &&
|
|
(PCIDeviceConfig.DeviceID == 0x001C)) {
|
|
|
|
PCIDeviceConfig.Command |= PCI_ENABLE_IO_SPACE;
|
|
PCIDeviceConfig.u.type0.BaseAddresses[0] = (ULONG)0x4100;
|
|
|
|
HalSetBusData (
|
|
PCIConfiguration,
|
|
0,
|
|
slot.u.AsULONG,
|
|
&PCIDeviceConfig,
|
|
sizeof (PCIDeviceConfig)
|
|
);
|
|
|
|
break;
|
|
} /* endif */
|
|
} /* endfor */
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
# define PmIoBase 0x4100
|
|
|
|
VOID
|
|
TurnOnLCD( BOOLEAN PowerState )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine turns on/off LCD.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN found = FALSE;
|
|
|
|
if (HalpInitPhase == 0)
|
|
found = HalpPhase0EnablePmController();
|
|
else
|
|
found = HalpPhase1EnablePmController();
|
|
|
|
if (!found) {
|
|
return;
|
|
} /* endif */
|
|
|
|
//
|
|
// Turns on/off LCD
|
|
//
|
|
|
|
if (PowerState) {
|
|
|
|
KeStallExecutionProcessor(100 * 1000); // wait 100ms for panel protection
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x0C);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x02);
|
|
|
|
KeStallExecutionProcessor(5 * 1000); // wait 5ms for DC/DC converter
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x0C);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x0c);
|
|
|
|
KeStallExecutionProcessor(1);
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x00);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x80);
|
|
|
|
KeStallExecutionProcessor(1);
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x0C);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x01);
|
|
|
|
} else {
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x0C);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x01);
|
|
|
|
KeStallExecutionProcessor(1);
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x00);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x80);
|
|
|
|
KeStallExecutionProcessor(1);
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x0C);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x0C);
|
|
|
|
KeStallExecutionProcessor(1);
|
|
|
|
WRITE_WD_UCHAR(PmIoBase, 0x0C);
|
|
WRITE_WD_UCHAR(PmIoBase + 1,
|
|
READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x02);
|
|
|
|
} /* endif */
|
|
|
|
} // end TurnOnLCD()
|