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.
 
 
 
 
 
 

1733 lines
42 KiB

/*++
Copyright (c) 1994, 95, 96 International Business Machines Corporation
Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
contains copyrighted material. Use of this file is restricted
by the provisions of a Motorola Software License Agreement.
Module Name:
pxdisp.c
Abstract:
This module implements the HAL display initialization and output routines
for a Sandalfoot PowerPC system using either an S3 or Weitek P9000
video adapter.
Author:
Jim Wooldridge Sept 1994 - Ported to PowerPC Initial Version
Environment:
Kernel mode
Revision History:
Jess Botts S3 support in text mode Oct-1993
Lee Nolan Added Weitek P9000 support Feb-1994
Mike Haskell Added Weitek P9100 support Oct-1994
Tim White Added GXT150P support Feb-1995
Jake Oshins Rearranged everything Jun-1995
--*/
#include "halp.h"
#include "pxs3.h"
#include "pxdisp.h"
#include "string.h"
#include "pxP91.h"
//=============================================================================
//
// IBMBJB added include to get text mode values for the Brooktree 485 DAC's
// palette registers, removed definition of HDAL and added address
// definitions for PowerPC
#include "txtpalet.h"
#include "pci.h"
#include "pcip.h"
#if defined(_PPC_)
# define VIDEO_ROM_OFFSET 0x000C0000
# define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
# define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
#endif
#define READ_VRAM(port) \
*(HalpVideoMemoryBase + (port))
#define WRITE_VRAM(port,data) \
*(HalpVideoMemoryBase + (port)) = (data), \
KeFlushWriteBuffer()
//PHYSICAL ADDRESS of WEITEK P9000 video ram
#define P9_VIDEO_MEMORY_BASE 0xC1200000
//PHYSICAL ADDRESS of WEITEK P9100 video ram
#define P91_VIDEO_MEMORY_BASE 0xC1800000
//PHYSICAL ADDRESS of S3 video ram
#define S3_VIDEO_MEMORY_BASE 0xC0000000
#define S3_928_DEVICE_ID 0x88B05333
#define S3_864_DEVICE_ID 0x88C05333
#define P9_DEVICE_ID 0x1300100E
#define P91_DEVICE_ID 0x9100100E
#define BBL_DEVICE_ID 0x001B1014
#define BL_DEVICE_ID 0x003C1014
#define WD_90C_DEVICE_ID 0xC24A101c
#define UNKNOWN_DEVICE_ID 0x0
#define MAX_PCI_BUSSES 256
//PHYSICAL ADDRESSES for GXT150P adapter
// (in bbldef.h)
// Include GXT150P header file information
//#include "bblrastz.h"
//#include "bblrmdac.h"
#include "bbldef.h"
#define TAB_SIZE 4
//
// Prototypes.
//
#if defined(_MP_PPC_)
VOID
HalpAcquireDisplayLock(
VOID
);
VOID
HalpReleaseDisplayLock(
VOID
);
#endif
VOID
HalpDisplayCharacterVgaViaBios (
IN UCHAR Character
);
VOID
HalpDispCharVgaViaBios (
IN UCHAR Character
);
VOID
HalpDisplaySetupVgaViaBios (
VOID
);
VOID
HalpPositionCursorVgaViaBios (
IN ULONG Row,
IN ULONG Column
);
VOID
ScrollScreenVgaViaBios (
IN UCHAR LinesToScroll
);
VOID
HalpSetupAndClearScreenVgaViaBios (
VOID
);
VOID
HalpDisplayCharacterS3 (
IN UCHAR Character
);
VOID
HalpDisplayPpcS3Setup (
VOID
);
VOID
HalpDisplayPpcWDSetup (
VOID
);
VOID
HalpCopyOEMFontFile();
VOID
WaitForVSync (
VOID
);
VOID
ScreenOn (
VOID
);
VOID
ScreenOff (
VOID
);
VOID
Scroll_Screen (
IN UCHAR line
);
#if !defined(WOODFIELD)
//
// Woodfield - IBM PowerPC LapTop machines don't support plug in PCI
// video adapters so don't pull the init code for those adapters into
// the HAL.
//
VOID
HalpDisplayPpcP9Setup (
VOID
);
VOID
HalpDisplayPpcP91Setup (
VOID
);
VOID
HalpDisplayPpcP91Setup (
VOID
);
VOID
HalpDisplayCharacterP91 (
IN UCHAR Character
);
VOID
HalpDisplayPpcBBLSetup (
VOID
);
VOID
HalpDisplayCharacterBBL (
IN UCHAR Character
);
VOID
HalpDisplayPpcBLSetup (
VOID
);
VOID
HalpDisplayCharacterBL (
IN UCHAR Character
);
#endif
//
//
//
typedef
VOID
(*PHALP_CONTROLLER_SETUP) (
VOID
);
typedef
VOID
(*PHALP_DISPLAY_CHARACTER) (
UCHAR
);
extern ULONG HalpPciMaxSlots;
extern BOOLEAN
HalpPhase0MapBusConfigSpace (
VOID
);
extern VOID
HalpPhase0UnMapBusConfigSpace (
VOID
);
extern VOID
HalpP91RelinquishDisplayOwnership();
//
// Define static data.
//
BOOLEAN HalpDisplayOwnedByHal;
volatile PUCHAR HalpVideoMemoryBase = (PUCHAR)0;
volatile PUCHAR HalpVideoCoprocBase = (PUCHAR)0;
PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
ULONG HalpDisplayPciDeviceId;
extern ULONG HalpInitPhase;
//
// Define OEM font variables.
//
USHORT HalpBytesPerRow;
USHORT HalpCharacterHeight;
USHORT HalpCharacterWidth;
ULONG HalpDisplayText;
ULONG HalpDisplayWidth;
ULONG HalpScrollLength;
ULONG HalpScrollLine;
//
// Define display variables.
//
ULONG HalpColumn;
ULONG HalpRow;
ULONG HalpHorizontalResolution;
ULONG HalpVerticalResolution;
UCHAR HalpDisplayIdentifier[256] = "";
BOOLEAN HalpDisplayTypeUnknown = FALSE;
POEM_FONT_FILE_HEADER HalpFontHeader;
extern ULONG HalpEnableInt10Calls;
#define PCI_DISPLAY_CONTROLLER 0x03
#define PCI_PRE_REV_2 0x0
BOOLEAN HalpBiosShadowed = FALSE;
ULONG HalpVideoBiosLength = 0;
PUCHAR HalpShadowBuffer;
extern UCHAR HalpShadowBufferPhase0;
BOOLEAN
HalpInitializeDisplay (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This routine maps the video memory and control registers into the user
part of the idle process address space, initializes the video control
registers, and clears the video screen.
Arguments:
LoaderBlock - Supplies a pointer to the loader parameter block.
Return Value:
If the initialization is successfully completed, than a value of TRUE
is returned. Otherwise, a value of FALSE is returned.
--*/
{
PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
ULONG MatchKey;
LONG SlotNumber = HalpPciMaxSlots - 1;
LONG BusNumber = 0;
ULONG VideoDeviceSlotNumber = HalpPciMaxSlots + 1; // start with an impossible value
ULONG VideoDeviceBusNumber = 0;
UCHAR BaseClassCode;
UCHAR SubClassCode;
ULONG Device_Vendor_Id;
ULONG RomBaseAddress;
ULONG PCICommand;
ULONG AmountRead = 1;
ULONG DeleteIoSpace = 0;
ULONG VgaBiosShadowOffset = 0xffffffff;
//
// For the Weitek P9100, set the address of the font file header.
// Display variables are computed later in HalpDisplayPpcP9Setup.
//
// This is changed as Phase 1 init starts. The font is copied
// out of the LoaderBlock and into non-paged pool so that it
// can be used again if the machine bluescreens.
//
HalpFontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
//
// Read the Registry entry to find out which video adapter the system
// is configured for. This code depends on the OSLoader to put the
// correct value in the Registry.
//
MatchKey = 0;
ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
ControllerClass,
DisplayController,
&MatchKey);
//
// Determine controller setup routine, display character routine, and PCI device id
// via configuration tree
//
if (ConfigurationEntry != NULL) {
if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"S3_928")) {
HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
HalpDisplayCharacter = HalpDisplayCharacterS3;
HalpDisplayPciDeviceId = S3_928_DEVICE_ID;
} else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"S3_864")) {
HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
HalpDisplayCharacter = HalpDisplayCharacterS3;
HalpDisplayPciDeviceId = S3_864_DEVICE_ID;
#if !defined(WOODFIELD)
} else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
HalpDisplayCharacter = HalpDisplayCharacterP91;
HalpDisplayPciDeviceId = P91_DEVICE_ID;
} else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"GXT150P")) {
HalpDisplayControllerSetup = HalpDisplayPpcBBLSetup;
HalpDisplayCharacter = HalpDisplayCharacterBBL;
HalpDisplayPciDeviceId = BBL_DEVICE_ID;
} else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"GXT250P")) {
HalpDisplayControllerSetup = HalpDisplayPpcBLSetup;
HalpDisplayCharacter = HalpDisplayCharacterBL;
HalpDisplayPciDeviceId = BL_DEVICE_ID;
#endif
} else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"WD_90C")) {
HalpDisplayControllerSetup = HalpDisplayPpcWDSetup;
HalpDisplayCharacter = HalpDisplayCharacterS3;
HalpDisplayPciDeviceId = WD_90C_DEVICE_ID;
}
} else {
HalpDisplayControllerSetup = NULL;
HalpDisplayCharacter = NULL;
HalpDisplayPciDeviceId = UNKNOWN_DEVICE_ID;
}
//
// Check to see if BIOS exists for the display controller
//
if (HalpPhase0MapBusConfigSpace() == TRUE) {
while (BusNumber < (LONG)HalpPciMaxBuses) {
SlotNumber = HalpPciMaxSlots - 1;
while (SlotNumber >= 0) {
//
// Just shut off all the video chips. We will re-enable
// the one we want later.
//
HalpPhase0GetPciDataByOffset(BusNumber,
SlotNumber,
&BaseClassCode,
FIELD_OFFSET(PCI_COMMON_CONFIG,
BaseClass),
sizeof(BaseClassCode));
HalpPhase0GetPciDataByOffset(BusNumber,
SlotNumber,
&SubClassCode,
FIELD_OFFSET(PCI_COMMON_CONFIG,
SubClass),
sizeof(SubClassCode));
//
// Is this a display adapter?
//
if (((BaseClassCode == PCI_DISPLAY_CONTROLLER) && (SubClassCode == 0)) ||
((BaseClassCode == PCI_PRE_REV_2) && (SubClassCode == 1))) {
HalpPhase0GetPciDataByOffset (
BusNumber,
SlotNumber,
&PCICommand,
FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
sizeof (PCICommand)
);
//
// Disble IO and Memory space decoding
//
PCICommand &= (~PCI_ENABLE_IO_SPACE &
~PCI_ENABLE_MEMORY_SPACE &
~PCI_ENABLE_BUS_MASTER);
HalpPhase0SetPciDataByOffset(BusNumber,
SlotNumber,
&PCICommand,
FIELD_OFFSET(PCI_COMMON_CONFIG,
Command),
sizeof (PCICommand)
);
}
//
// If we have already found a video card, skip
// the following section
//
if (VideoDeviceSlotNumber < HalpPciMaxSlots) {
SlotNumber--;
continue;
}
//
// Now test to see if this is the one ARC used. (This algorithm
// will identify either the chip with the same ID that ARC used
// or, in the case that we don't recognize the ID, the chip in
// the highest slot number that is a video device.
if (HalpDisplayPciDeviceId == UNKNOWN_DEVICE_ID) {
//
// Is this a display adapter?
//
if (((BaseClassCode == PCI_DISPLAY_CONTROLLER) && (SubClassCode == 0)) ||
((BaseClassCode == PCI_PRE_REV_2) && (SubClassCode == 1))) {
// This is the one we want to use, so save the slot number
VideoDeviceSlotNumber = SlotNumber;
VideoDeviceBusNumber = BusNumber;
}
} else {
//
// Find the pci slot of the display controller
//
HalpPhase0GetPciDataByOffset(BusNumber,
SlotNumber,
&Device_Vendor_Id,
0,
sizeof(Device_Vendor_Id));
//
// In the following, when we apply a mask to the
// Device_Vendor_Id it's to hide the chip revision.
//
if ( ((Device_Vendor_Id & 0xFFF0FFFF) == S3_928_DEVICE_ID) ||
((Device_Vendor_Id & 0xFFF0FFFF) == S3_864_DEVICE_ID) ||
((Device_Vendor_Id & 0xFFF0FFFF) == P9_DEVICE_ID) ||
((Device_Vendor_Id & 0xFFF0FFFF) == P91_DEVICE_ID) ||
( Device_Vendor_Id == BBL_DEVICE_ID) ||
( Device_Vendor_Id == BL_DEVICE_ID) ||
( Device_Vendor_Id == WD_90C_DEVICE_ID) ) {
VideoDeviceSlotNumber = SlotNumber;
VideoDeviceBusNumber = BusNumber;
}
}
SlotNumber--;
}
BusNumber++;
}
if (VideoDeviceSlotNumber < HalpPciMaxSlots) {
//
// Turn the video chip back on
//
HalpPhase0GetPciDataByOffset(VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&PCICommand,
FIELD_OFFSET(PCI_COMMON_CONFIG,
Command),
sizeof (PCICommand)
);
PCICommand |= PCI_ENABLE_IO_SPACE |
PCI_ENABLE_MEMORY_SPACE |
PCI_ENABLE_BUS_MASTER;
HalpPhase0SetPciDataByOffset (VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&PCICommand,
FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
sizeof (PCICommand)
);
//
// Determine what ROM base address should be
//
// Writing 0xFFFFFFFE to the register and then reading it tells us what
// our bounds are.
RomBaseAddress = 0xFFFFFFFE;
HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&RomBaseAddress,
FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
sizeof(RomBaseAddress));
HalpPhase0GetPciDataByOffset(VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&RomBaseAddress,
FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
sizeof(RomBaseAddress));
//
// Strip lowest bit, which is for enabling decoders.
//
RomBaseAddress &= 0xFFFFFFFE;
//
// This sets the least significant bit that we were able to change,
// which tells us how much space we need for the BIOS.
//
RomBaseAddress = ((~RomBaseAddress) + 1) & RomBaseAddress;
// If this ROM is small enough, put it in the normal VGA ROM position
if (RomBaseAddress <= 0x10000) {
RomBaseAddress = 0x00c0000;
}
else {
RomBaseAddress = 0;
}
RomBaseAddress = RomBaseAddress | 0x00000001; //Switch on ROM decoding
//
// Now write it all back
//
HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&RomBaseAddress,
FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
sizeof(RomBaseAddress));
//
// Now map I/O memory space so we can look at the BIOS
//
HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
0x400000); // 4 MB
HalpIoMemoryBase = HalpVideoMemoryBase;
//
// Test to see if there is a BIOS present
//
if ((*((PUSHORT)HalpIoMemoryBase + (0xc0000 / 2))) == 0xaa55) {
VgaBiosShadowOffset = 0xc0000;
} else if ((*((PUSHORT)HalpIoMemoryBase)) == 0xaa55) {
VgaBiosShadowOffset = 0x0;
}
if (VgaBiosShadowOffset != 0xffffffff) {
//
// Shadow the BIOS
//
HalpVideoBiosLength = (*((PUCHAR)HalpIoMemoryBase + VgaBiosShadowOffset + 2)) * 512;
HalpShadowBuffer = &HalpShadowBufferPhase0;
RtlCopyMemory(HalpShadowBuffer,
(PUCHAR)HalpIoMemoryBase + VgaBiosShadowOffset,
HalpVideoBiosLength);
HalpBiosShadowed = TRUE;
//
// Try INT10
//
HalpInitializeX86DisplayAdapter(VideoDeviceBusNumber,
VideoDeviceSlotNumber);
}
if (HalpEnableInt10Calls == TRUE) {
HalpDisplayControllerSetup = HalpDisplaySetupVgaViaBios;
HalpDisplayCharacter = HalpDisplayCharacterVgaViaBios;
} else {
KePhase0DeleteIoMap(PCI_MEMORY_PHYSICAL_BASE, 0x400000);
HalpVideoMemoryBase = NULL;
HalpIoMemoryBase = NULL;
}
//
// If the BIOS might be too large to leave mapped into ISA expansion
// space, stop decoding the BIOS because we have either shadowed it
// or it didn't exist in the first place.
//
// I would unmap all BIOSes, but the S3 chips seem to stop working if I do. -- Jake
if ((RomBaseAddress & 0xFFFFFFFE) == 0) {
RomBaseAddress = 0;
HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&RomBaseAddress,
FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
sizeof(RomBaseAddress));
//
// Turn the video chip back on because the previous call may have turned it off
//
HalpPhase0GetPciDataByOffset (VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&PCICommand,
FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
sizeof (PCICommand)
);
PCICommand |= PCI_ENABLE_IO_SPACE |
PCI_ENABLE_MEMORY_SPACE |
PCI_ENABLE_BUS_MASTER;
HalpPhase0SetPciDataByOffset (VideoDeviceBusNumber,
VideoDeviceSlotNumber,
&PCICommand,
FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
sizeof (PCICommand)
);
}
}
HalpPhase0UnMapBusConfigSpace();
}
// Save the display type in a global variable for use in the
// HalAcquireDisplayOwnership() function
strcpy(HalpDisplayIdentifier,
ConfigurationEntry->ComponentEntry.Identifier);
//
// Initialize the display controller.
//
if (HalpDisplayControllerSetup != NULL) {
HalpDisplayControllerSetup();
}
return TRUE;
}
VOID
HalpCopyBiosShadow(
VOID
)
/*++
Routine Description:
This routine checks to see if there is a BIOS image in
HalpShadowBuffer and copies it to a block of non-paged
pool. This is done because HalpShadowBuffer will be
thrown away at the end of Phase 1. The idea is to
avoid wasting non-paged pool when we aren't using a
video BIOS.
Arguments:
None.
Return Value:
None.
--*/
{
ASSERT(HalpInitPhase == 1);
if (HalpBiosShadowed) {
HalpShadowBuffer = ExAllocatePool(NonPagedPool, HalpVideoBiosLength);
ASSERT(HalpShadowBuffer);
RtlCopyMemory((PVOID)HalpShadowBuffer,
(PVOID)&HalpShadowBufferPhase0,
HalpVideoBiosLength);
}
}
VOID
HalAcquireDisplayOwnership (
IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
)
/*++
Routine Description:
This routine switches ownership of the display away from the HAL to
the system display driver. It is called when the system has reached
a point during bootstrap where it is self supporting and can output
its own messages. Once ownership has passed to the system display
driver any attempts to output messages using HalDisplayString must
result in ownership of the display reverting to the HAL and the
display hardware reinitialized for use by the HAL.
Arguments:
None.
Return Value:
None.
--*/
{
#if !defined(WOODFIELD)
if (!strcmp(HalpDisplayIdentifier, "GXT150P")){
//
// Deleting access to the frame buffer here since we are about
// to give ownership of the display adapter to the miniport so
// we'll never touch the adapter again unless the system panics
// at which point we re-initialize anyway
//
// KePhase0DeleteIoMap(BBL_VIDEO_MEMORY_BASE,
// BBL_VIDEO_MEMORY_LENGTH);
}
else if (!strcmp(HalpDisplayIdentifier, "P9100")) {
// HalpP91RelinquishDisplayOwnership();
}
#endif
//
// Set HAL ownership of the display to false.
//
HalpDisplayOwnedByHal = FALSE;
return;
}
VOID
HalpDisplaySetupVgaViaBios (
VOID
)
/*++
Routine Description:
This routine initializes a vga controller via bios reset.
Arguments:
None.
Return Value:
None.
--*/
{
//
// Routine Description:
//
//
ULONG DataLong;
PHYSICAL_ADDRESS physicalAddress;
XM86_CONTEXT Context ;
if (HalpInitPhase == 0) {
HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
0x400000); // 4 MB
}
HalpSetupAndClearScreenVgaViaBios () ;
//
// Initialize the current display column, row, and ownership values.
//
HalpColumn = 0;
HalpRow = 0;
HalpDisplayWidth = 80;
HalpDisplayText = 50;
HalpDisplayOwnedByHal = TRUE;
return;
} /* end of HalpDisplaySetupVgaViaBios() */
VOID
HalpDisplayCharacterVgaViaBios (
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
ScrollScreenVgaViaBios (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) ) {
ScrollScreenVgaViaBios (1) ; // scroll the screen up
} else {
++HalpRow;
}
}
} else if (Character == '\r') {
HalpColumn = 0;
} else if (Character == 0x7f) { /* DEL character */
if (HalpColumn != 0) {
HalpColumn -= 1;
HalpPositionCursorVgaViaBios( HalpRow, HalpColumn ) ;
HalpDispCharVgaViaBios(0x20);
}
} else if (Character >= 0x20) {
//
// Auto wrap for HalpDisplayWidth columns per line
//
if (HalpColumn >= HalpDisplayWidth) {
HalpColumn = 0;
if (HalpRow < (HalpDisplayText - 1)) {
HalpRow += 1;
} else { // need to scroll up the screen
ScrollScreenVgaViaBios (1);
}
}
HalpPositionCursorVgaViaBios( HalpRow, HalpColumn ) ;
HalpDispCharVgaViaBios (Character) ;
HalpColumn++ ;
}
return;
}
VOID
HalpPositionCursorVgaViaBios (
IN ULONG Row,
IN ULONG Column
)
/*++
Routine Description:
This routine positions the cusor at a specified location.
Arguments:
Row - row position for the cursor
Column - column position for the cursor
Return Value:
None.
--*/
{
XM86_CONTEXT Context ;
// position the cursor
Context.Eax = 0x0200 ;
Context.Ebx = 0x0000 ;
Context.Edx = (Row << 8) | Column ;
if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
(HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
)
{
DbgPrint( "HalpPositionCursorVgaViaBios: FAILED\n" ) ;
}
return ;
}
VOID
HalpDispCharVgaViaBios (
IN UCHAR Character
)
/*++
Routine Description:
This routine prints a charcter at the current cursor positions.
Arguments:
Character - character to be printed
Return Value:
None.
--*/
{
XM86_CONTEXT Context ;
// display the character
Context.Eax = 0x0900 | Character ;
Context.Ebx = 0x001f ;
Context.Ecx = 1 ;
if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
(HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
)
{
DbgPrint( "HalpDispCharVgaViaBios: Putchar Call Failed\n" ) ;
}
return ;
}
VOID
ScrollScreenVgaViaBios (
IN UCHAR LinesToScroll
)
/*++
Routine Description:
This routine scrolls the screen up by "LinesToScroll" number of lines.
Arguments:
LinesToScroll - number of lines to scroll up.
Return Value:
None.
--*/
{
XM86_CONTEXT Context ;
// scroll screen up
Context.Eax = 0x0600 | LinesToScroll ;
Context.Ebx = 0x1f00 ;
Context.Ecx = 0 ;
Context.Edx = 0x314f ;
if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
(HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
)
{
DbgPrint( "ScrollScreenVgaViaBios: Scroll screen up Failed\n" ) ;
}
return;
}
VOID
HalpSetupAndClearScreenVgaViaBios ( VOID
)
/*++
Routine Description:
This routine sets up the text mode 3, loads ROM double dot set and
clears the screen.
Arguments:
None
Return Value:
None.
--*/
{
XM86_CONTEXT Context ;
ULONG x,y ;
// Switch Adaptor to text mode 3
Context.Eax = 0x0003 ;
if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
(HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
)
{
DbgPrint( "HalpSetupAndClearScreenVgaViaBios: Switch Adaptor to text mode 3 FAILED\n" ) ;
}
// load ROM double dot set
Context.Eax = 0x1112 ;
Context.Ebx = 0 ;
if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
(HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
)
{
DbgPrint( "HalpSetupAndClearScreenVgaViaBios: load ROM double dot set FAILED\n" ) ;
}
for ( x = 0; x < 50 ; x++ )
for ( y = 0; y < 80; y++ ) {
HalpPositionCursorVgaViaBios (x, y) ;
HalpDispCharVgaViaBios ( 0x20 ) ;
}
HalpColumn = 0;
HalpRow = 0;
HalpPositionCursorVgaViaBios (HalpRow, HalpColumn) ;
return ;
}
VOID
HalDisplayString (
PUCHAR String
)
/*++
Routine Description:
This routine displays a character string on the display screen.
Arguments:
String - Supplies a pointer to the characters that are to be displayed.
Return Value:
None.
--*/
{
KIRQL OldIrql;
//
// Raise IRQL to the highest level, flush the TB, and map the display
// frame buffer into the address space of the current process.
//
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#if defined(_MP_PPC_)
HalpAcquireDisplayLock();
#endif
//
// If ownership of the display has been switched to the system display
// driver, then reinitialize the display controller and revert ownership
// to the HAL.
//
if (HalpDisplayControllerSetup != NULL) {
if (HalpDisplayOwnedByHal == FALSE) {
HalpDisplayControllerSetup();
}
//
// Display characters until a null byte is encountered.
//
while (*String != 0) {
HalpDisplayCharacter(*String++);
}
}
//
// Restore the previous mapping for the current process, flush the TB,
// and lower IRQL to its previous level.
//
#if defined(_MP_PPC_)
HalpReleaseDisplayLock();
#endif
KeLowerIrql(OldIrql);
return;
} /* end of HalpDisplayString() */
VOID
HalQueryDisplayParameters (
OUT PULONG WidthInCharacters,
OUT PULONG HeightInLines,
OUT PULONG CursorColumn,
OUT PULONG CursorRow
)
/*++
Routine Description:
This routine return information about the display area and current
cursor position.
Arguments:
WidthInCharacter - Supplies a pointer to a varible that receives
the width of the display area in characters.
HeightInLines - Supplies a pointer to a variable that receives the
height of the display area in lines.
CursorColumn - Supplies a pointer to a variable that receives the
current display column position.
CursorRow - Supplies a pointer to a variable that receives the
current display row position.
Return Value:
None.
--*/
{
//
// Set the display parameter values and return.
//
*WidthInCharacters = HalpDisplayWidth; //IBMLAN
*HeightInLines = HalpDisplayText;
*CursorColumn = HalpColumn;
*CursorRow = HalpRow;
return;
}
VOID
HalSetDisplayParameters (
IN ULONG CursorColumn,
IN ULONG CursorRow
)
/*++
Routine Description:
This routine set the current cursor position on the display area.
Arguments:
CursorColumn - Supplies the new display column position.
CursorRow - Supplies a the new display row position.
Return Value:
None.
--*/
{
//
// Set the display parameter values and return.
//
if (CursorColumn > HalpDisplayWidth) { //IBMLAN
CursorColumn = HalpDisplayWidth; //IBMLAN
}
if (CursorRow > HalpDisplayText) {
CursorRow = HalpDisplayText;
}
HalpColumn = CursorColumn;
HalpRow = CursorRow;
return;
}
VOID
HalpCopyOEMFontFile()
{
PVOID buffer;
buffer = ExAllocatePool(NonPagedPool,
HalpFontHeader->FileSize);
ASSERT(buffer);
RtlCopyMemory(buffer,
HalpFontHeader,
HalpFontHeader->FileSize);
HalpFontHeader = buffer;
}
//
// HalpS3Xxx functions can now be found in pxs3.c
//
//
// The following functions were left here in pxdisp.c
// because they are used by multiple display modules.
//
VOID
Scroll_Screen(IN UCHAR line)
{
UCHAR i, DataByte;
ULONG target, stop;
for (i = 0; i < line; i ++) {
WaitForVSync(); // wait for vertical sync to make scroll smooth
target = 0xb8000;
stop = target + HalpScrollLength;
for (; target < stop; target += 2) {
DataByte = READ_S3_VRAM(target+HalpScrollLine);
WRITE_S3_VRAM(target, DataByte);
}
stop += HalpScrollLine;
for (; target < stop; target += 2) {
WRITE_S3_VRAM(target, 0x20 );
}
}
}
VOID
WaitForVSync (VOID)
{
UCHAR DataByte;
BOOLEAN test;
//
// Determine 3Dx or 3Bx
//
DataByte = READ_S3_UCHAR(MiscOutR);
ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
// Unlock S3 ( S3R8 )
// UnLockS3();
//
// Test Chip ID = '81h' ?
//
// For standard VGA text mode this action is not necessary.
// WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
// if ((DataByte = READ_S3_UCHAR(S3_3D5_Data)) == 0x81) {
//
// Wait For Verttical Retrace
//
test = TRUE;
while (test) {
READ_S3_UCHAR(Stat1_In);
READ_S3_UCHAR(Stat1_In);
READ_S3_UCHAR(Stat1_In);
test = READ_S3_UCHAR(Stat1_In) & 0x08 ? FALSE : TRUE;
}
// Wait for H/V blanking
test = TRUE;
while (test) {
READ_S3_UCHAR(Stat1_In);
READ_S3_UCHAR(Stat1_In);
READ_S3_UCHAR(Stat1_In);
test = READ_S3_UCHAR(Stat1_In) & 0x01 ? TRUE : FALSE;
}
// }
// Lock S3 ( S3R8 )
// LockS3();
return;
} /* end of WaitForVsync() */
VOID ScreenOn(VOID)
{
UCHAR DataByte;
WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
WRITE_S3_UCHAR(Seq_Data, 0x01);
WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
DataByte = READ_S3_UCHAR(Seq_Data);
DataByte = DataByte & 0xdf;
WRITE_S3_UCHAR(Seq_Data, DataByte);
WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
WRITE_S3_UCHAR(Seq_Data, 0x03);
return;
}
VOID ScreenOff(VOID)
{
UCHAR DataByte;
WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
WRITE_S3_UCHAR(Seq_Data, 0x01);
WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
DataByte = READ_S3_UCHAR(Seq_Data);
DataByte = DataByte | 0x20;
WRITE_S3_UCHAR(Seq_Data, DataByte);
WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
WRITE_S3_UCHAR(Seq_Data, 0x03);
return;
}
// These functions are commented out because the video adapter they
// are here to support has no support in NT anymore. I'm not
// deleting them because we may want to add them back some day. - Jake
// VOID
// HalpDisplayPpcP9Setup (
// VOID
// )
// /*++
//
// Routine Description:
//
// This routine initializes the Weitek P9000 display contoller chip.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
// --*/
// {
// PULONG buffer;
// ULONG limit, index;
// PHYSICAL_ADDRESS physicalAddress;
//
// // For now I'll leave the P9000 in the same state that the firmware
// // left it in. This should be 640x480.
//
// HalpHorizontalResolution = 640;
// HalpVerticalResolution = 480;
//
// if (HalpInitPhase == 0) {
//
// HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(P9_VIDEO_MEMORY_BASE,
// 0x400000); // 4 MB
//
// } else {
//
// //
// // Map video memory space via pte's
// //
//
// physicalAddress.HighPart = 0;
// physicalAddress.LowPart = P9_VIDEO_MEMORY_BASE;
// HalpVideoMemoryBase = MmMapIoSpace(physicalAddress,
// 0x400000,
// FALSE);
//
// //
// // IO control space has already been mapped in phase 1 via halpmapiospace
// //
//
// }
//
// //IBMLAN Use font file from OS Loader
// //
// // Compute display variables using using HalpFontHeader which is
// // initialized in HalpInitializeDisplay().
// //
// // N.B. The font information suppled by the OS Loader is used during phase
// // 0 initialization. During phase 1 initialization, a pool buffer is
// // allocated and the font information is copied from the OS Loader
// // heap into pool.
// //
// //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
// //HalpFontHeader = FontHeader;
// HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
// HalpCharacterHeight = HalpFontHeader->PixelHeight;
// HalpCharacterWidth = HalpFontHeader->PixelWidth;
//
// //
// // Compute character output display parameters.
// //
//
// HalpDisplayText =
// HalpVerticalResolution / HalpCharacterHeight;
//
// HalpScrollLine =
// HalpHorizontalResolution * HalpCharacterHeight;
//
// HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
//
// HalpDisplayWidth =
// HalpHorizontalResolution / HalpCharacterWidth;
//
//
// //
// // Set the video memory to address color one.
// //
//
// buffer = (PULONG)HalpVideoMemoryBase;
// limit = (HalpHorizontalResolution *
// HalpVerticalResolution) / sizeof(ULONG);
//
// for (index = 0; index < limit; index += 1) {
// *buffer++ = 0x01010101;
// }
//
//
// //
// // Initialize the current display column, row, and ownership values.
// //
//
// HalpColumn = 0;
// HalpRow = 0;
// HalpDisplayOwnedByHal = TRUE;
// return;
//
// } //end of HalpDisplayPpcP9Setup
//
// VOID
// HalpDisplayCharacterP9 (
// 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 encountered, the frame buffer is
// scrolled. If characters extend below the end of line, they are not
// displayed.
//
// Arguments:
//
// Character - Supplies a character to be displayed.
//
// Return Value:
//
// None.
//
// --*/
//
// {
//
// PUCHAR Destination;
// PUCHAR Source;
// ULONG Index;
//
// //
// // 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 {
// //RtlMoveMemory((PVOID)P9_VIDEO_MEMORY_BASE,
// // (PVOID)(P9_VIDEO_MEMORY_BASE + HalpScrollLineP9),
// // HalpScrollLengthP9);
//
// // Scroll up one line
// Destination = HalpVideoMemoryBase;
// Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
// for (Index = 0; Index < HalpScrollLength; Index++) {
// *Destination++ = *Source++;
// }
// // Blue the bottom line
// Destination = HalpVideoMemoryBase + HalpScrollLength;
// for (Index = 0; Index < HalpScrollLine; Index += 1) {
// *Destination++ = 1;
// }
// }
//
// } else if (Character == '\r') {
// HalpColumn = 0;
//
// } else {
// if ((Character < HalpFontHeader->FirstCharacter) ||
// (Character > HalpFontHeader->LastCharacter)) {
// Character = HalpFontHeader->DefaultCharacter;
// }
//
// Character -= HalpFontHeader->FirstCharacter;
// HalpOutputCharacterP9((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
// }
//
// return;
// }
//
// VOID
// HalpOutputCharacterP9(
// IN PUCHAR Glyph
// )
//
// /*++
//
// Routine Description:
//
// This routine insert a set of pixels into the display at the current x
// cursor position. If the current x cursor position is at the end of the
// line, then a newline is displayed before the specified character.
//
// Arguments:
//
// Character - Supplies a character to be displayed.
//
// Return Value:
//
// None.
//
// --*/
//
// {
//
// PUCHAR Destination;
// ULONG FontValue;
// ULONG tmp;
// ULONG I;
// ULONG J;
//
// //
// // If the current x cursor position is at the end of the line, then
// // output a line feed before displaying the character.
// //
//
// if (HalpColumn == HalpDisplayWidth) {
// HalpDisplayCharacterP9('\n');
// }
//
// //
// // Output the specified character and update the x cursor position.
// //
//
// Destination = (PUCHAR)(HalpVideoMemoryBase +
// (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
//
// for (I = 0; I < HalpCharacterHeight; I += 1) {
// FontValue = 0;
// for (J = 0; J < HalpBytesPerRow; J += 1) {
// FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
// }
// // Move the font bits around so the characters look right.
// tmp = (FontValue >> 3) & 0x11111111; //bits 7 and 3 to the right 3
// tmp |= (FontValue >> 1) & 0x22222222; //bits 6 and 2 to the right 1
// tmp |= (FontValue << 1) & 0x44444444; //bits 5 and 1 to the left 1
// tmp |= (FontValue << 3) & 0x88888888; //bits 4 and 0 to the left 3
// FontValue = tmp;
//
// Glyph += 1;
// for (J = 0; J < HalpCharacterWidth ; J += 1) {
// if (FontValue >> 31 != 0)
// *Destination = 0xFF; //Make this pixel white
//
// Destination++;
// //*Destination++ = (FontValue >> 31) ^ 1;
// FontValue <<= 1;
// }
//
// Destination +=
// (HalpHorizontalResolution - HalpCharacterWidth);
// }
//
// HalpColumn += 1;
// return;
// }
//
// HalpP91Xxx functions can now be found in pxp91.c
//
//
// HalpBBLXxx functions can now be found in pxbbl.c
//