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.
2907 lines
77 KiB
2907 lines
77 KiB
/*
|
|
* Copyright (c) 1995 FirePower Systems, Inc.
|
|
* DO NOT DISTRIBUTE without permission
|
|
*
|
|
* $RCSfile: pxdisp.c $
|
|
* $Revision: 1.44 $
|
|
* $Date: 1996/07/02 04:58:11 $
|
|
* $Locker: $
|
|
*/
|
|
|
|
/*++
|
|
|
|
Copyright (c) 1994 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
|
|
Roger Lanser 02-23-95: Added FirePower Video and INT10, nuc'd others
|
|
|
|
--*/
|
|
|
|
#include "halp.h"
|
|
#include "pxs3.h" // BUGBUG: generic output?
|
|
#include "string.h"
|
|
#include "fpbat.h"
|
|
#include "arccodes.h"
|
|
#include "phsystem.h"
|
|
#include "pxmemctl.h"
|
|
#include "fpdcc.h"
|
|
#include "fpcpu.h"
|
|
#include "fpdebug.h"
|
|
#include "phsystem.h"
|
|
#include "x86bios.h"
|
|
#include "pxpcisup.h"
|
|
#include "pxcirrus.h"
|
|
|
|
#define MAX_DBATS 4
|
|
|
|
// for test only
|
|
NTSYSAPI
|
|
NTSTATUS
|
|
NTAPI
|
|
RtlCharToInteger (
|
|
PCSZ String,
|
|
ULONG Base,
|
|
PULONG Value
|
|
);
|
|
|
|
//=============================================================================
|
|
//
|
|
// 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"
|
|
|
|
// PCI Vendor ID & Device ID
|
|
#define PCI_VENDOR_ID_WEITEK 0x100e
|
|
#define PCI_DEVICE_ID_WEITEK_P9000 0x9001
|
|
#define PCI_DEVICE_ID_WEITEK_P9100 0x9100
|
|
#define PCI_VENDOR_ID_S3 0x5333
|
|
#define PCI_DEVICE_ID_S3_864_1 0x88c0
|
|
#define PCI_DEVICE_ID_S3_864_2 0x88c1
|
|
|
|
#if defined(_PPC_)
|
|
|
|
#define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
|
|
#define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
|
|
|
|
#endif
|
|
|
|
#define ROWS 25
|
|
#define COLS 80
|
|
#define TAB_SIZE 4
|
|
#define ONE_LINE (80*2)
|
|
#define TWENTY_FOUR_LINES 24*ONE_LINE
|
|
#define TWENTY_FIVE_LINES 25*ONE_LINE
|
|
#define TEXT_ATTR 0x1F
|
|
|
|
//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
|
|
|
|
#if DBG
|
|
extern VOID HalpDisplayBatForVRAM ( void );
|
|
# define TRACE Trace
|
|
#else
|
|
# define TRACE
|
|
#endif
|
|
|
|
BOOLEAN
|
|
HalpInitializeX86DisplayAdapter(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
//
|
|
// Define forward referenced procedure prototypes.
|
|
//
|
|
BOOLEAN HalpDisplayINT10Setup (VOID);
|
|
VOID HalpOutputCharacterINT10 (IN UCHAR Character );
|
|
VOID HalpScrollINT10 (IN UCHAR line);
|
|
VOID HalpDisplayCharacterVGA (IN UCHAR Character );
|
|
VOID HalpDisplayCharacterVgaViaBios (IN UCHAR Character);
|
|
VOID HalpOutputCharacterVgaViaBios (IN UCHAR AsciiChar);
|
|
BOOLEAN HalpDisplaySetupVgaViaBios (VOID);
|
|
|
|
|
|
BOOLEAN HalpDisplayPowerizedGrapicsSetup (ULONG);
|
|
BOOLEAN HalpDisplayPowerizedGraphicsSetup (VOID);
|
|
VOID HalpDisplayCharacterPowerizedGraphics (IN UCHAR Character);
|
|
VOID HalpOutputCharacterPowerizedGraphics (IN PUCHAR Glyph);
|
|
BOOLEAN HalpInitializeDisplay (IN PLOADER_PARAMETER_BLOCK LoaderBlock);
|
|
|
|
|
|
VOID HalpOutputCharacterS3 (IN UCHAR AsciiChar);
|
|
BOOLEAN HalpDisplayPpcS3Setup (VOID);
|
|
VOID HalpScrollS3(IN UCHAR line);
|
|
BOOLEAN HalpDisplayPpcP91Setup (VOID);
|
|
VOID HalpDisplayCharacterP91 (IN UCHAR Character);
|
|
VOID HalpOutputCharacterP91(IN PUCHAR Glyph);
|
|
BOOLEAN HalpDisplayPpcP91BlankScreen (VOID);
|
|
VOID HalpDisplayCharacterCirrus(IN UCHAR Character);
|
|
VOID HalpOutputCharacterCirrus(IN UCHAR AsciiChar);
|
|
BOOLEAN HalpDisplayPpcCirrusSetup(VOID);
|
|
VOID HalpScrollCirrus(IN UCHAR line);
|
|
|
|
static void updattr(IN int rg,IN unsigned char val);
|
|
static void set_ext_regs(IN int reg,IN unsigned char *p);
|
|
static void clear_text(VOID);
|
|
static void load8x16(VOID);
|
|
static void load_ramdac();
|
|
|
|
|
|
//
|
|
// Put all code for HAL initialization in the INIT section. It will be
|
|
// deallocated by memory management when phase 1 initialization is
|
|
// completed.
|
|
//
|
|
#if defined(ALLOC_PRAGMA)
|
|
#pragma alloc_text(INIT, HalpInitializeDisplay)
|
|
#pragma alloc_text(INIT, HalpInitializeVRAM)
|
|
#if DBG
|
|
#pragma alloc_text(INIT, HalpDisplayBatForVRAM)
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(NT_UP)
|
|
ULONG HalpDisplayLock;
|
|
#endif // !defined(NT_UP)
|
|
|
|
|
|
typedef VOID (*PHALP_SCROLL_SCREEN) (UCHAR);
|
|
typedef VOID (*PHALP_OUTPUT_CHARACTER) (UCHAR);
|
|
typedef BOOLEAN (*PHALP_CONTROLLER_SETUP) (VOID);
|
|
typedef VOID (*PHALP_DISPLAY_CHARACTER) (UCHAR);
|
|
|
|
//
|
|
// Define global data.
|
|
//
|
|
ULONG HalpVideoMemorySize = (ULONG)DISPLAY_MEMORY_SIZE;
|
|
PUCHAR HalpVideoMemoryBase = (PUCHAR)NULL;
|
|
|
|
//
|
|
// Define static data.
|
|
//
|
|
|
|
static ULONG PowerizedGraphicsDisplayMode = 0; // default 640x480
|
|
static PVOID HalpVideoConfigBase = NULL;
|
|
static BOOLEAN HalpDisplayOwnedByHal = FALSE; // make sure is false: [breeze:1/27/95]
|
|
static PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
|
|
static PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
|
|
static PHALP_OUTPUT_CHARACTER HalpOutputCharacter = NULL;
|
|
static PHALP_SCROLL_SCREEN HalpScrollScreen = NULL;
|
|
|
|
//
|
|
// 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;
|
|
USHORT HalpHorizontalResolution;
|
|
USHORT HalpVerticalResolution;
|
|
USHORT HalpScreenStart = 0; // for cirrus
|
|
|
|
BOOLEAN HalpDisplayTypeUnknown = FALSE;
|
|
|
|
POEM_FONT_FILE_HEADER HalpFontHeader;
|
|
|
|
extern ULONG HalpEnableInt10Calls;
|
|
#define PCI_DISPLAY_CONTROLLER 0x03
|
|
#define PCI_PRE_REV_2 0x0
|
|
#define DISPLAY_CLASS 0x03
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
#if DBG
|
|
static VOID
|
|
Trace(PCHAR Format, ...)
|
|
|
|
{
|
|
va_list arglist;
|
|
UCHAR Buffer[256];
|
|
ULONG Length;
|
|
if (HalpDebugValue & DBG_DISPLAY) {
|
|
va_start(arglist, Format);
|
|
Length = vsprintf(Buffer, Format, arglist);
|
|
DbgPrint(Buffer);
|
|
}
|
|
}
|
|
#endif
|
|
/*----------------------------------------------------------------------------*/
|
|
#define SEQ_CLKMODE_INDEX 0x01
|
|
#define SEQ_MISC_INDEX 0x11
|
|
#define SEQ_OUTPUT_CTL_INDEX 0x12 /* Vendor specific */
|
|
|
|
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;
|
|
}
|
|
|
|
#undef MIN
|
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
#undef MAX
|
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
|
#define CRYSTAL_FREQUENCY (14318180 * 2)
|
|
#define MIN_VCO_FREQUENCY 50000000
|
|
#define MAX_NUMERATOR 130
|
|
#define MAX_DENOMINATOR MIN(129, CRYSTAL_FREQUENCY / 400000)
|
|
#define MIN_DENOMINATOR MAX(3, CRYSTAL_FREQUENCY / 2000000)
|
|
|
|
#define CLOCK(x) WRITE_S3_UCHAR(MiscOutW, (UCHAR)(iotemp | (x)))
|
|
#define C_DATA 0x0c
|
|
#define C_CLK 0x04
|
|
#define C_BOTH 0x08
|
|
#define C_NONE 0x00
|
|
|
|
long vclk_range[16] = {
|
|
0, // should be MIN_VCO_FREQUENCY, but that causes problems.
|
|
51000000,
|
|
53200000,
|
|
58500000,
|
|
60700000,
|
|
64400000,
|
|
66800000,
|
|
73500000,
|
|
75600000,
|
|
80900000,
|
|
83200000,
|
|
91500000,
|
|
100000000,
|
|
120000000,
|
|
285000000,
|
|
0,
|
|
};
|
|
/******************************************************************************
|
|
* Number theoretic function - GCD (Greatest Common Divisor)
|
|
*****************************************************************************/
|
|
static long gcd(a, b)
|
|
register long a, b;
|
|
{
|
|
register long c = a % b;
|
|
while (c)
|
|
a = b, b = c, c = a % b;
|
|
return b;
|
|
}
|
|
/****************************************************************************
|
|
* calc_clock
|
|
*
|
|
* Usage: clock frequency [set]
|
|
* frequency is specified in MHz
|
|
*
|
|
***************************************************************************/
|
|
static long calc_clock(frequency, select)
|
|
|
|
register long frequency; /* in Hz */
|
|
int select;
|
|
{
|
|
register long index;
|
|
long temp;
|
|
long min_m, min_n, min_diff;
|
|
long diff;
|
|
|
|
int clock_m;
|
|
int clock_n;
|
|
int clock_p;
|
|
|
|
min_diff = 0xFFFFFFF;
|
|
min_n = 1;
|
|
min_m = 1;
|
|
|
|
/* Calculate 18 bit clock value */
|
|
|
|
clock_p = 0;
|
|
if (frequency < MIN_VCO_FREQUENCY)
|
|
clock_p = 1;
|
|
if (frequency < MIN_VCO_FREQUENCY / 2)
|
|
clock_p = 2;
|
|
if (frequency < MIN_VCO_FREQUENCY / 4)
|
|
clock_p = 3;
|
|
|
|
frequency <<= clock_p;
|
|
|
|
for (clock_n = 4; clock_n <= MAX_NUMERATOR; clock_n++)
|
|
{
|
|
index = CRYSTAL_FREQUENCY / (frequency / clock_n);
|
|
|
|
if (index > MAX_DENOMINATOR)
|
|
index = MAX_DENOMINATOR;
|
|
if (index < MIN_DENOMINATOR)
|
|
index = MIN_DENOMINATOR;
|
|
|
|
for (clock_m = index - 3; clock_m < index + 4; clock_m++)
|
|
if (clock_m >= MIN_DENOMINATOR && clock_m <= MAX_DENOMINATOR)
|
|
{
|
|
diff = (CRYSTAL_FREQUENCY / clock_m) * clock_n - frequency;
|
|
|
|
if (diff < 0)
|
|
diff = -diff;
|
|
|
|
if (min_m * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_m &&
|
|
min_n * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_n)
|
|
|
|
if (diff > min_diff)
|
|
diff = min_diff;
|
|
|
|
if (diff <= min_diff)
|
|
{
|
|
min_diff = diff;
|
|
min_m = clock_m;
|
|
min_n = clock_n;
|
|
}
|
|
}
|
|
}
|
|
|
|
clock_m = min_m;
|
|
clock_n = min_n;
|
|
|
|
/* Calculate the index */
|
|
|
|
temp = (((CRYSTAL_FREQUENCY / 2) * clock_n) / clock_m) << 1;
|
|
for (index = 0; vclk_range[index + 1] < temp && index < 15; index++)
|
|
;
|
|
|
|
/* Pack the clock value for the frequency snthesizer */
|
|
|
|
temp = (((long)clock_n - 3) << 11) + ((clock_m - 2) << 1)
|
|
+ (clock_p << 8) + (index << 18) + ((long)select << 22);
|
|
|
|
return temp;
|
|
|
|
}
|
|
static VOID SetICD2061AClock(LONG clock_value) /* 7bits M, 7bits N, 2bits P */
|
|
{
|
|
register long index;
|
|
register char iotemp;
|
|
int select;
|
|
|
|
select = (clock_value >> 22) & 3;
|
|
|
|
/* Shut off screen */
|
|
ScreenOff();
|
|
|
|
iotemp = READ_S3_UCHAR(MiscOutR);
|
|
|
|
/* Program the IC Designs 2061A frequency generator */
|
|
|
|
CLOCK(C_NONE);
|
|
|
|
/* Unlock sequence */
|
|
|
|
CLOCK(C_DATA);
|
|
for (index = 0; index < 6; index++)
|
|
{
|
|
CLOCK(C_BOTH);
|
|
CLOCK(C_DATA);
|
|
}
|
|
CLOCK(C_NONE);
|
|
CLOCK(C_CLK);
|
|
CLOCK(C_NONE);
|
|
CLOCK(C_CLK);
|
|
|
|
/* Program the 24 bit value into REG0 */
|
|
|
|
for (index = 0; index < 24; index++)
|
|
{
|
|
/* Clock in the next bit */
|
|
clock_value >>= 1;
|
|
if (clock_value & 1)
|
|
{
|
|
CLOCK(C_CLK);
|
|
CLOCK(C_NONE);
|
|
CLOCK(C_DATA);
|
|
CLOCK(C_BOTH);
|
|
}
|
|
else
|
|
{
|
|
CLOCK(C_BOTH);
|
|
CLOCK(C_DATA);
|
|
CLOCK(C_NONE);
|
|
CLOCK(C_CLK);
|
|
}
|
|
}
|
|
|
|
CLOCK(C_BOTH);
|
|
CLOCK(C_DATA);
|
|
CLOCK(C_BOTH);
|
|
|
|
/* If necessary, reprogram other ICD2061A registers to defaults */
|
|
|
|
/* Select the CLOCK in the frequency synthesizer */
|
|
|
|
TRACE("select=%d\n", select);
|
|
CLOCK(C_NONE | select);
|
|
|
|
/* Turn screen back on */
|
|
ScreenOn();
|
|
}
|
|
|
|
static VOID EnableMemoryAndIO(PCI_CONFIG configBase)
|
|
{
|
|
USHORT Cmd;
|
|
// Enable Memory & I/O spaces in command register. Firmware does not always set this.
|
|
Cmd = READ_REGISTER_USHORT(&configBase->Command);
|
|
//TRACE("Cmd=0x%x->", Cmd);
|
|
Cmd = Cmd | 3;
|
|
//TRACE("0x%x\n", Cmd);
|
|
WRITE_REGISTER_USHORT(&configBase->Command, Cmd);
|
|
}
|
|
|
|
static VOID MakeP9100VGA(PVOID pConfigBase)
|
|
{
|
|
UCHAR DataByte;
|
|
|
|
//TRACE("MakeP9100VGA: starting\n");
|
|
/* Disable the P9000 and enable VGA.*/
|
|
/* unlocking the 5186/5286 registers */
|
|
WRITE_S3_UCHAR(Seq_Index, SEQ_MISC_INDEX);
|
|
DataByte = READ_S3_UCHAR(Seq_Data); /* Read misc register */
|
|
WRITE_S3_UCHAR(Seq_Data, DataByte);
|
|
WRITE_S3_UCHAR(Seq_Data, DataByte); /* Write back twice */
|
|
DataByte = READ_S3_UCHAR(Seq_Data); /* Read misc register again */
|
|
WRITE_S3_UCHAR(Seq_Data, DataByte & ~0x20); /* Clear bit 5 */
|
|
|
|
DataByte = READ_REGISTER_UCHAR(((PCHAR)pConfigBase)+65);
|
|
TRACE("HalpVideoConfigBase+65 DataByte=0x%02x->", DataByte);
|
|
DataByte = DataByte | 0x0e; // bit 1 VGA emulation
|
|
DataByte = 0xe2;
|
|
WRITE_REGISTER_UCHAR(((PCHAR)pConfigBase)+65, DataByte); // this makes display blank
|
|
DataByte = READ_REGISTER_UCHAR(((PCHAR)pConfigBase)+65);
|
|
TRACE("0x%02x\n", DataByte);
|
|
|
|
{
|
|
ULONG ul;
|
|
ULONG clock_numbers;
|
|
|
|
ul = 25175000;
|
|
clock_numbers = calc_clock(ul, 2);
|
|
SetICD2061AClock(clock_numbers);
|
|
}
|
|
}
|
|
|
|
static BOOLEAN
|
|
WorkAroundBeforeInitBIOS()
|
|
{
|
|
USHORT vendorID = 0;
|
|
USHORT deviceID = 0;
|
|
UCHAR revisionID = 0;
|
|
UCHAR Class;
|
|
UCHAR SubClass;
|
|
int i;
|
|
BOOLEAN Found = FALSE;
|
|
|
|
for (i = 1 /* skip SIO */; ((i < MAXIMUM_PCI_SLOTS) && (Found == FALSE)); i++) {
|
|
HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[i]);
|
|
|
|
Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
|
|
SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
|
|
if ((Class == DISPLAY_CLASS && (SubClass == 0)) ||
|
|
(Class == 0x00 && SubClass == 0x01)) { // pre-rev 2.0 display card
|
|
|
|
vendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
|
|
deviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
|
|
revisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
|
|
TRACE("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", vendorID, deviceID, revisionID);
|
|
|
|
if ((vendorID == PCI_VENDOR_ID_WEITEK) && (deviceID == PCI_DEVICE_ID_WEITEK_P9100)) { //viper Pro
|
|
EnableMemoryAndIO(HalpVideoConfigBase);
|
|
MakeP9100VGA(HalpVideoConfigBase); // let BIOS initialize chip
|
|
}
|
|
}
|
|
}
|
|
return Found;
|
|
}
|
|
|
|
/* firmware gives 'VGA' even when S3 card is in. */
|
|
static BOOLEAN
|
|
WorkAroundAfterInitBIOS()
|
|
{
|
|
USHORT vendorID = 0;
|
|
USHORT deviceID = 0;
|
|
UCHAR revisionID = 0;
|
|
UCHAR Class;
|
|
UCHAR SubClass;
|
|
int i;
|
|
BOOLEAN Found = FALSE;
|
|
|
|
TRACE("WorkAroundAfterInitBIOS starting.\n");
|
|
|
|
for (i = 1; ((i < MAXIMUM_PCI_SLOTS) && (Found == FALSE)); i++) {
|
|
HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[i]);
|
|
|
|
Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
|
|
SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
|
|
TRACE("ClassID=0x%02x SubClass=0x%02x\n", Class, SubClass);
|
|
|
|
if ((Class == DISPLAY_CLASS && (SubClass == 0)) ||
|
|
(Class == 0x00 && SubClass == 0x01)) { // pre-rev 2.0 display card
|
|
|
|
vendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
|
|
deviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
|
|
revisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
|
|
TRACE("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", vendorID, deviceID, revisionID);
|
|
|
|
if (vendorID == PCI_VENDOR_ID_S3) {
|
|
EnableMemoryAndIO(HalpVideoConfigBase);
|
|
HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
|
|
HalpDisplayCharacter = HalpDisplayCharacterVGA;
|
|
HalpOutputCharacter = HalpOutputCharacterS3;
|
|
HalpScrollScreen = HalpScrollS3;
|
|
Found = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return Found;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: BOOLEAN HalpInitializeDisplay ()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
BOOLEAN
|
|
HalpInitializeDisplay (
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
{
|
|
PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
|
|
ULONG MatchKey;
|
|
BOOLEAN Found = FALSE;
|
|
CHAR buf[BUFSIZ];
|
|
BOOLEAN bUseVGA = TRUE; // TRUE: scan SVGA cards. FALSE: ignore SVGA cards.
|
|
|
|
//IBMLAN Use font file from OS Loader
|
|
//
|
|
// For the Weitek P9000, set the address of the font file header.
|
|
// Display variables are computed later in HalpDisplayPpcP9Setup.
|
|
//
|
|
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);
|
|
|
|
if (NULL == ConfigurationEntry) {
|
|
TRACE("ConfigurationEntry is NULL.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (HalGetEnvironmentVariable("DISPLAY", sizeof(buf), buf) == ESUCCESS) {
|
|
TRACE("DISPLAY='%s'\n", buf);
|
|
bUseVGA = FALSE;
|
|
}
|
|
TRACE("HalpInitializeDisplay: ConfigurationEntry->ComponentEntry.Identifier='%s'\n", ConfigurationEntry->ComponentEntry.Identifier);
|
|
|
|
while ((TRUE == bUseVGA) && (FALSE == Found)) {
|
|
Found = WorkAroundBeforeInitBIOS();
|
|
if (TRUE == Found) break;
|
|
|
|
//
|
|
// Don't look for a PCI video adapter if the environment
|
|
// variable "DISPLAY" is defined.
|
|
//
|
|
if (HalpPciConfigBase) {
|
|
TRACE("HalpIoMemoryBase = 0x%08x\n", HalpIoMemoryBase);
|
|
TRACE("HalpPciConfigBase = 0x%08x\n", HalpPciConfigBase);
|
|
TRACE("HalpIoControlBase = 0x%08x\n", HalpIoControlBase);
|
|
|
|
if (HalpInitializeX86DisplayAdapter(LoaderBlock)) {
|
|
TRACE("HalpInitializeX86DisplayAdapter() succeeded.\n");
|
|
HalpDisplayControllerSetup = HalpDisplayINT10Setup;
|
|
HalpDisplayCharacter = HalpDisplayCharacterVGA;
|
|
HalpOutputCharacter = HalpOutputCharacterINT10;
|
|
HalpScrollScreen = HalpScrollINT10;
|
|
Found = TRUE;
|
|
} else {
|
|
TRACE("HalpInitializeX86DisplayAdapter() failed.\n");
|
|
}
|
|
}
|
|
if (TRUE == Found) break;
|
|
|
|
Found = WorkAroundAfterInitBIOS();
|
|
if (TRUE == Found) break;
|
|
|
|
if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
|
|
HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
|
|
HalpDisplayCharacter = HalpDisplayCharacterP91;
|
|
Found = TRUE;
|
|
} else if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"S3")) {
|
|
HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
|
|
HalpDisplayCharacter = HalpDisplayCharacterVGA;
|
|
HalpOutputCharacter = HalpOutputCharacterS3;
|
|
HalpScrollScreen = HalpScrollS3;
|
|
Found = TRUE;
|
|
} else {
|
|
// Unsupported VGA display identifier or probably Powerized Graphics.
|
|
bUseVGA = FALSE;
|
|
}
|
|
} /* while */
|
|
|
|
while (FALSE == Found) {
|
|
if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"Powerized Graphics")) {
|
|
HalpDisplayControllerSetup = HalpDisplayPowerizedGraphicsSetup;
|
|
HalpDisplayCharacter = HalpDisplayCharacterPowerizedGraphics;
|
|
//
|
|
// Set mode 15 which is 1024x768 60 Hz
|
|
//
|
|
PowerizedGraphicsDisplayMode = 15;
|
|
if (HalGetEnvironmentVariable("DISPLAY", sizeof(buf), buf) == ESUCCESS) {
|
|
if (!_stricmp(buf, "VGA")) {
|
|
//
|
|
// Just in case someone wants mode 0 (VGA)
|
|
//
|
|
PowerizedGraphicsDisplayMode = 0;
|
|
}
|
|
}
|
|
Found = TRUE;
|
|
} else if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"VGA")) {
|
|
//
|
|
// This is where the INT10 could go if the firmware were
|
|
// to be trusted.
|
|
// Just put the framebuffer in VGA mode for now.
|
|
//
|
|
HalpDisplayControllerSetup = HalpDisplayPowerizedGraphicsSetup;
|
|
HalpDisplayCharacter = HalpDisplayCharacterPowerizedGraphics;
|
|
//
|
|
// Set mode 0 which is 640x480 60 Hz
|
|
//
|
|
PowerizedGraphicsDisplayMode = 0;
|
|
Found = TRUE;
|
|
} else {
|
|
HalDisplayString("can't happen\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
//===========end=IBMLAN===============================================
|
|
|
|
//
|
|
// Initialize the display controller.
|
|
//
|
|
|
|
if (HalpDisplayControllerSetup != NULL) {
|
|
return HalpDisplayControllerSetup();
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: VOID HalAcquireDisplayOwnership ()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalAcquireDisplayOwnership (
|
|
IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
|
|
)
|
|
{
|
|
|
|
//
|
|
// Set HAL ownership of the display to false.
|
|
//
|
|
|
|
HalpDisplayOwnedByHal = FALSE;
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: VOID HalDisplayString ()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalDisplayString (
|
|
PUCHAR String
|
|
)
|
|
{
|
|
|
|
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);
|
|
|
|
KiAcquireSpinLock(&HalpDisplayAdapterLock);
|
|
|
|
//
|
|
// 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++);
|
|
}
|
|
}
|
|
|
|
KiReleaseSpinLock(&HalpDisplayAdapterLock);
|
|
|
|
//
|
|
// Restore the previous mapping for the current process, flush the TB,
|
|
// and lower IRQL to its previous level.
|
|
//
|
|
KeLowerIrql(OldIrql);
|
|
return;
|
|
|
|
} /* end of HalpDisplayString() */
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: VOID HalQueryDisplayParameters ()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalQueryDisplayParameters (
|
|
OUT PULONG WidthInCharacters,
|
|
OUT PULONG HeightInLines,
|
|
OUT PULONG CursorColumn,
|
|
OUT PULONG CursorRow
|
|
)
|
|
{
|
|
|
|
//
|
|
// Set the display parameter values and return.
|
|
//
|
|
KiAcquireSpinLock(&HalpDisplayAdapterLock);
|
|
|
|
*WidthInCharacters = HalpDisplayWidth; //IBMLAN
|
|
*HeightInLines = HalpDisplayText;
|
|
*CursorColumn = HalpColumn;
|
|
*CursorRow = HalpRow;
|
|
|
|
KiReleaseSpinLock(&HalpDisplayAdapterLock);
|
|
return;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: VOID HalSetDisplayParameters ()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalSetDisplayParameters (
|
|
IN ULONG CursorColumn,
|
|
IN ULONG CursorRow
|
|
)
|
|
{
|
|
|
|
//
|
|
// Set the display parameter values and return.
|
|
//
|
|
KiAcquireSpinLock(&HalpDisplayAdapterLock);
|
|
|
|
if (CursorColumn > HalpDisplayWidth) { //IBMLAN
|
|
CursorColumn = HalpDisplayWidth; //IBMLAN
|
|
}
|
|
|
|
if (CursorRow > HalpDisplayText) {
|
|
CursorRow = HalpDisplayText;
|
|
}
|
|
|
|
HalpColumn = CursorColumn;
|
|
HalpRow = CursorRow;
|
|
KiReleaseSpinLock(&HalpDisplayAdapterLock);
|
|
return;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: BOOLEAN HalpDisplaySetupVgaViaBios ()
|
|
|
|
This routine initializes a vga controller via bios reset.
|
|
Arguments:
|
|
None.
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
BOOLEAN
|
|
HalpDisplaySetupVgaViaBios (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Routine Description:
|
|
//
|
|
//
|
|
|
|
ULONG DataLong;
|
|
|
|
HalpResetX86DisplayAdapter();
|
|
|
|
//
|
|
// Set screen into blue
|
|
//
|
|
|
|
for (DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2) {
|
|
WRITE_S3_VRAM(DataLong, 0x20);
|
|
WRITE_S3_VRAM(DataLong+1, 0x1F);
|
|
}
|
|
|
|
//
|
|
// Initialize the current display column, row, and ownership values.
|
|
//
|
|
|
|
HalpColumn = 0;
|
|
HalpRow = 0;
|
|
HalpDisplayWidth = 80;
|
|
HalpDisplayText = 25;
|
|
HalpScrollLine = 160;
|
|
HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
|
|
|
|
HalpDisplayOwnedByHal = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
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
|
|
Scroll_Screen(IN UCHAR line)
|
|
{
|
|
UCHAR i, DataByte;
|
|
ULONG target;
|
|
|
|
for (i = 0; i < line; i ++) {
|
|
//=======================================================================
|
|
//
|
|
// IBMBJB added wait for vertical sync to make scroll smooth
|
|
|
|
WaitForVSync();
|
|
|
|
//=======================================================================
|
|
|
|
for (target = 0xB8000; target < 0xB8F00; target += 2) {
|
|
DataByte = READ_S3_VRAM(target+0xA0);
|
|
WRITE_S3_VRAM(target, DataByte);
|
|
}
|
|
for (target = 0xB8F00; target < 0xB8FA0; target += 2) {
|
|
WRITE_S3_VRAM(target, 0x20 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
Routine Description: VOID HalpDisplayCharacterVgaViaBios ()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalpDisplayCharacterVgaViaBios (
|
|
IN UCHAR Character
|
|
)
|
|
{
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
//=========================================================================
|
|
//
|
|
// IBMBJB added tab processing
|
|
//
|
|
|
|
else if( Character == '\t' ) // tab?
|
|
{
|
|
HalpColumn += TAB_SIZE;
|
|
HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
|
|
|
|
if( HalpColumn >= 80 ) // 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;
|
|
HalpOutputCharacterVgaViaBios(0);
|
|
HalpColumn -= 1;
|
|
} else /* do nothing */
|
|
;
|
|
} else if (Character >= 0x20) {
|
|
// Auto wrap for 80 columns per line
|
|
if (HalpColumn >= 80) {
|
|
HalpColumn = 0;
|
|
if (HalpRow < (HalpDisplayText - 1)) {
|
|
HalpRow += 1;
|
|
} else { // need to scroll up the screen
|
|
Scroll_Screen(1);
|
|
}
|
|
}
|
|
HalpOutputCharacterVgaViaBios(Character);
|
|
} else /* skip the nonprintable character */
|
|
;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: VOID HalpOutputCharacterVgaViaBios ()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalpOutputCharacterVgaViaBios (
|
|
IN UCHAR AsciiChar
|
|
)
|
|
{
|
|
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 < 80) {
|
|
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;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/* Following code (to EOF) added for PowerPro HAL Display Support [ged]. */
|
|
/*************************************************************************/
|
|
|
|
BOOLEAN
|
|
HalpInitializeDisplay1 (
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
{
|
|
PVOID fontheader;
|
|
|
|
// Use font file from OS Loader
|
|
//
|
|
// During phase 1 initialization, a pool buffer is
|
|
// allocated and the font information is copied from
|
|
// the OS Loader heap into pool.
|
|
//
|
|
|
|
fontheader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize );
|
|
if(fontheader == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
RtlMoveMemory(fontheader, HalpFontHeader, HalpFontHeader->FileSize );
|
|
HalpFontHeader = (POEM_FONT_FILE_HEADER) fontheader;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: BOOLEAN HalpDisplayPowerizedGraphicsSetup ()
|
|
|
|
This routine initializes the FirePower 'Powerized Graphics' frame buffer.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
If the initialization is successfully completed, than a value of TRUE
|
|
is returned. Otherwise, a value of FALSE is returned.
|
|
|
|
--*/
|
|
|
|
BOOLEAN
|
|
HalpDisplayPowerizedGraphicsSetup (
|
|
VOID
|
|
)
|
|
{
|
|
PULONG buffer;
|
|
ULONG limit, index;
|
|
static ULONG vramWidth; // mogawa BUG3449
|
|
static BOOLEAN onetime = TRUE;
|
|
|
|
|
|
/* NOTE: The following line remaps the virtual to physical mapping */
|
|
/* of DBAT3 to the physical address of PowerPro's frame */
|
|
/* buffer. This overrides the Kernel's mapping to PCI memory. */
|
|
/* If Motorola changes this, we need to revisit it! [ged] */
|
|
/* NOTE2: For speed, we may want to make this region cacheable. */
|
|
|
|
// Moved dbat mapping to init routines to remove it from normal code
|
|
// path [breeze-7.15.94]
|
|
//
|
|
// Moved mapping back here so various adapters can be supported,
|
|
// without getting the frame buffer init'd in the mainline init.
|
|
// [rlanser-02.06.95]
|
|
|
|
|
|
if (onetime) {
|
|
|
|
onetime = FALSE;
|
|
|
|
HalpVideoMemoryBase =
|
|
HalpInitializeVRAM( (PVOID)DISPLAY_MEMORY_BASE, &HalpVideoMemorySize, &vramWidth);
|
|
|
|
//
|
|
// Set FrameBuffer Control Register
|
|
//
|
|
// Use a mask value of 7
|
|
//
|
|
|
|
{
|
|
ULONG ul = rFbControl;
|
|
ul &= ~0x07000000;
|
|
ul |= 0x07000000 & (vramWidth ? 0x0 : 0x03000000);
|
|
rFbControl = ul;
|
|
FireSyncRegister();
|
|
}
|
|
|
|
if (!HalpVideoMemoryBase) {
|
|
HalpDebugPrint("HalpVideoMemoryBase did not map...%x,%x\n",
|
|
HalpVideoMemoryBase,HalpVideoMemorySize);
|
|
HDBG(DBG_BREAK, DbgBreakPoint(););
|
|
return FALSE;
|
|
}
|
|
|
|
HDBG(DBG_GENERAL,
|
|
HalpDebugPrint("HalpVideoMemoryBase is: 0x%x\n",
|
|
HalpVideoMemoryBase););
|
|
HDBG(DBG_GENERAL,
|
|
HalpDebugPrint("HalpIoControlBase = 0x%x\n",
|
|
HalpIoControlBase););
|
|
}
|
|
|
|
if (15 == PowerizedGraphicsDisplayMode) {
|
|
HalpSetupDCC(15, vramWidth); // mode 15 - 1024x768 8 bit 60Hz
|
|
HalpHorizontalResolution = 1024;
|
|
HalpVerticalResolution = 768;
|
|
} else {
|
|
HalpSetupDCC(0, vramWidth); // mode 0 - 640x480 8 bit 60Hz
|
|
HalpHorizontalResolution = 640;
|
|
HalpVerticalResolution = 480;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Since we use a cached Video Controler sweep the video memory
|
|
// range.
|
|
//
|
|
HalSweepDcacheRange(HalpVideoMemoryBase, HalpVideoMemorySize);
|
|
|
|
//
|
|
// Initialize the current display column, row, and ownership values.
|
|
//
|
|
|
|
HalpColumn = 0;
|
|
HalpRow = 0;
|
|
HalpDisplayOwnedByHal = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
} /* HalpDisplayPowerizedGraphicsSetup */
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: VOID HalpDisplayCharacterPowerizedGraphics ()
|
|
|
|
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 beyond the end of line, they are not
|
|
displayed.
|
|
|
|
Arguments:
|
|
|
|
Character - Supplies a character to be displayed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalpDisplayCharacterPowerizedGraphics (
|
|
IN UCHAR Character
|
|
)
|
|
{
|
|
|
|
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)PRO_VIDEO_MEMORY_BASE,
|
|
// (PVOID)(PRO_VIDEO_MEMORY_BASE + HalpScrollLine),
|
|
// HalpScrollLength);
|
|
|
|
// 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 == '\t' ) { // tab?
|
|
HalpColumn += TAB_SIZE;
|
|
HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
|
|
|
|
// tab beyond end of screen?
|
|
if (HalpColumn >= HalpDisplayWidth) {
|
|
// next tab stop is 1st column of next line
|
|
HalpColumn = 0;
|
|
|
|
if( HalpRow >= (HalpDisplayText - 1) ) {
|
|
HalpDisplayCharacterPowerizedGraphics('\n');
|
|
} else {
|
|
HalpRow++;
|
|
}
|
|
}
|
|
|
|
} else if (Character == '\r') {
|
|
HalpColumn = 0;
|
|
|
|
} else if (Character == 0x7f) { /* DEL character */
|
|
if (HalpColumn != 0) {
|
|
HalpColumn--;
|
|
HalpDisplayCharacterPowerizedGraphics(' ');
|
|
HalpColumn--;
|
|
}
|
|
|
|
} else if (Character >= 0x20) {
|
|
if ((Character < HalpFontHeader->FirstCharacter) ||
|
|
(Character > HalpFontHeader->LastCharacter)) {
|
|
Character = HalpFontHeader->DefaultCharacter;
|
|
}
|
|
Character -= HalpFontHeader->FirstCharacter;
|
|
HalpOutputCharacterPowerizedGraphics((PUCHAR)HalpFontHeader + \
|
|
HalpFontHeader->Map[Character].Offset);
|
|
} /* else skip the nonprintable character */
|
|
|
|
return;
|
|
} /* HalpDisplayCharacterPowerizedGraphics */
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: VOID HalpOutputCharacterPowerizedGraphics()
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
VOID
|
|
HalpOutputCharacterPowerizedGraphics(
|
|
IN PUCHAR Glyph
|
|
)
|
|
{
|
|
|
|
PUCHAR Destination;
|
|
ULONG FontValue;
|
|
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) {
|
|
HalpDisplayCharacterPowerizedGraphics('\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));
|
|
}
|
|
|
|
Glyph += 1;
|
|
for (J = 0; J < HalpCharacterWidth ; J += 1) {
|
|
if (FontValue >> 31 != 0) {
|
|
*Destination = 0xFF; //Make this pixel white
|
|
} else {
|
|
*Destination = 0x01; //Make this pixel blue
|
|
}
|
|
HalSweepDcacheRange(Destination, 1); // Push it out
|
|
Destination++;
|
|
//*Destination++ = (FontValue >> 31) ^ 1;
|
|
FontValue <<= 1;
|
|
}
|
|
|
|
Destination +=
|
|
(HalpHorizontalResolution - HalpCharacterWidth);
|
|
}
|
|
|
|
HalpColumn += 1;
|
|
|
|
return;
|
|
|
|
} /* HalpOutputCharacterPowerizedGraphics */
|
|
|
|
|
|
///
|
|
/// Debug
|
|
///
|
|
|
|
VOID
|
|
HalpDebugPrint(
|
|
|
|
PCHAR Format,
|
|
...
|
|
)
|
|
|
|
{
|
|
va_list arglist;
|
|
UCHAR Buffer[256];
|
|
ULONG Length;
|
|
|
|
//
|
|
// Format the output into a buffer and then print it.
|
|
//
|
|
|
|
va_start(arglist, Format);
|
|
Length = vsprintf(Buffer, Format, arglist);
|
|
if (HalpDisplayOwnedByHal) {
|
|
HalDisplayString(Buffer);
|
|
}
|
|
DbgPrint(Buffer);
|
|
}
|
|
|
|
VOID
|
|
HalpForceDisplay(
|
|
PCHAR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list arglist;
|
|
UCHAR Buffer[256];
|
|
ULONG Length;
|
|
|
|
//
|
|
// Format the output into a buffer and then display it.
|
|
//
|
|
va_start(arglist, Format);
|
|
Length = vsprintf(Buffer, Format, arglist);
|
|
HalDisplayString(Buffer);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------------*/
|
|
VOID
|
|
HalpDisplayCharacterVGA (
|
|
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
|
|
HalpScrollScreen(1);
|
|
}
|
|
}
|
|
|
|
//=========================================================================
|
|
//
|
|
// IBMBJB added tab processing
|
|
//
|
|
|
|
else if( Character == '\t' ) // tab?
|
|
{
|
|
HalpColumn += TAB_SIZE;
|
|
HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
|
|
|
|
if( HalpColumn >= 80 ) // tab beyond end of screen?
|
|
{
|
|
HalpColumn = 0; // next tab stop is 1st column of next line
|
|
|
|
if( HalpRow >= (HalpDisplayText - 1) )
|
|
HalpScrollScreen( 1 ); // scroll the screen up
|
|
else
|
|
++HalpRow;
|
|
}
|
|
}
|
|
|
|
//=========================================================================
|
|
|
|
else if (Character == '\r') {
|
|
HalpColumn = 0;
|
|
} else if (Character == 0x7f) { /* DEL character */
|
|
if (HalpColumn != 0) {
|
|
HalpColumn -= 1;
|
|
HalpOutputCharacter(0);
|
|
HalpColumn -= 1;
|
|
} else /* do nothing */
|
|
;
|
|
} else if (Character >= 0x20) {
|
|
// Auto wrap for 80 columns per line
|
|
if (HalpColumn >= 80) {
|
|
HalpColumn = 0;
|
|
if (HalpRow < (HalpDisplayText - 1)) {
|
|
HalpRow += 1;
|
|
} else { // need to scroll up the screen
|
|
HalpScrollScreen(1);
|
|
}
|
|
}
|
|
HalpOutputCharacter(Character);
|
|
} else /* skip the nonprintable character */
|
|
;
|
|
|
|
return;
|
|
|
|
} /* end of HalpDisplayCharacterVGA() */
|
|
|
|
VOID HalpOutputCharacterINT10 (
|
|
IN UCHAR Character)
|
|
{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
|
|
|
|
Eax = 2 << 8; // AH = 2
|
|
Ebx = 0; // BH = page number
|
|
Edx = (HalpRow << 8) + HalpColumn;
|
|
HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
|
|
|
|
Eax = (0x0A << 8) + Character; // AH = 0xA AL = character
|
|
Ebx = 0;
|
|
Ecx = 1;
|
|
HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
|
|
|
|
HalpColumn += 1;
|
|
|
|
}
|
|
|
|
|
|
VOID HalpScrollINT10 (
|
|
IN UCHAR LinesToScroll)
|
|
|
|
{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
|
|
|
|
Eax = 6 << 8; // AH = 6 (scroll up)
|
|
Eax |= LinesToScroll; // AL = lines to scroll
|
|
Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s)
|
|
Ecx = 0; // CH,CL = upper left
|
|
Edx = (24 << 8) + 79; // DH,DL = lower right
|
|
HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
|
|
}
|
|
|
|
BOOLEAN HalpDisplayINT10Setup (VOID)
|
|
{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
|
|
|
|
HalpColumn = 0;
|
|
HalpRow = 0;
|
|
HalpDisplayWidth = 80;
|
|
HalpDisplayText = 25;
|
|
HalpScrollLine = 160;
|
|
HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
|
|
|
|
HalpDisplayOwnedByHal = TRUE;
|
|
|
|
//
|
|
// Set cursor to (0,0)
|
|
//
|
|
Eax = 0x02 << 8; // AH = 2
|
|
Ebx = 0; // BH = page Number
|
|
Edx = 0; // DH = row DL = column
|
|
HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
|
|
|
|
//
|
|
// Make screen white on blue by scrolling entire screen
|
|
//
|
|
Eax = 0x06 << 8; // AH = 6 AL = 0
|
|
Ebx = TEXT_ATTR << 8; // BH = attribute
|
|
Ecx = 0; // (x,y) upper left
|
|
Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right
|
|
Edx += HalpScrollLine/2;
|
|
HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
|
|
|
|
return TRUE;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
BOOLEAN
|
|
HalpDisplayPpcS3Setup (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine initializes the S3 display controller chip.
|
|
Arguments:
|
|
None.
|
|
Return Value:
|
|
TRUE if finished successfully
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// 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;
|
|
|
|
|
|
if (HalpVideoMemoryBase == NULL) {
|
|
TRACE("HalpDisplayPpcS3Setup: calling KePhase0MapIo(S3_VIDEO_MEMORY_BASE,0x400000).\n");
|
|
HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)S3_VIDEO_MEMORY_BASE,
|
|
0x400000); // 4 MB
|
|
}
|
|
|
|
// Enable Video Subsystem
|
|
// Accordint to chapter 5.4.2 regular VGA setup sequence
|
|
TRACE("HalpDisplayPpcS3Setup: starting.\n");
|
|
|
|
//=========================================================================
|
|
//
|
|
// IBMBJB changed from writing 0x10 and then 0x08 to writing 0x18
|
|
// because the second write will wipe out the first one, the
|
|
// second write was originally done after the write to Setup_OP
|
|
//
|
|
// WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
|
|
// WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
|
|
|
|
WRITE_S3_UCHAR(SUBSYS_ENB, 0x18);
|
|
|
|
//=========================================================================
|
|
|
|
TRACE(" Subsystem Enable = 0x10...\n");
|
|
WRITE_S3_UCHAR(Setup_OP, 0x01);
|
|
|
|
|
|
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]);
|
|
}
|
|
|
|
|
|
// 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
|
|
TRACE(" 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
|
|
TRACE(" 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 );
|
|
WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
|
|
|
|
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)
|
|
TRACE(" 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
|
|
//
|
|
TRACE(" Set Screen into Blue ...\n");
|
|
for (DataLong = 0xB8000;
|
|
DataLong < 0xB8000+TWENTY_FIVE_LINES;
|
|
DataLong += 2) {
|
|
WRITE_S3_VRAM(DataLong, ' ');
|
|
WRITE_S3_VRAM(DataLong+1, TEXT_ATTR);
|
|
}
|
|
// 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 TRUE;
|
|
} /* end of HalpDisplayPpcS3Setup() */
|
|
|
|
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 < 80) {
|
|
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() */
|
|
|
|
|
|
|
|
VOID
|
|
HalpScrollS3(IN UCHAR line)
|
|
{
|
|
UCHAR i, DataByte;
|
|
ULONG target;
|
|
|
|
for (i = 0; i < line; i ++) {
|
|
//=======================================================================
|
|
//
|
|
// IBMBJB added wait for vertical sync to make scroll smooth
|
|
|
|
WaitForVSync();
|
|
|
|
//=======================================================================
|
|
|
|
for (target = 0xB8000;
|
|
target < 0xB8000+TWENTY_FOUR_LINES;
|
|
target += 2) {
|
|
DataByte = READ_S3_VRAM(target+ONE_LINE);
|
|
WRITE_S3_VRAM(target, DataByte);
|
|
}
|
|
for (target = 0xB8000+TWENTY_FOUR_LINES;
|
|
target < 0xB8000+TWENTY_FIVE_LINES;
|
|
target += 2) {
|
|
WRITE_S3_VRAM(target, ' ' );
|
|
}
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static PUCHAR HalpP91VideoMemoryBase = (PUCHAR)0;
|
|
|
|
BOOLEAN
|
|
HalpDisplayPpcP91Setup (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the Weitek P9100 display contoller chip.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PULONG buffer;
|
|
ULONG limit, index;
|
|
TRACE("HalpDisplayPpcP91Setup: starting...\n");
|
|
// For now I'll leave the P9100 in the same state that the firmware
|
|
// left it in. This should be 640x480.
|
|
|
|
HalpHorizontalResolution = 640;
|
|
HalpVerticalResolution = 480;
|
|
|
|
if (HalpP91VideoMemoryBase == NULL) {
|
|
|
|
HalpP91VideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)P91_VIDEO_MEMORY_BASE,
|
|
0x800000); // 8 MB
|
|
}
|
|
|
|
//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)HalpP91VideoMemoryBase;
|
|
limit = (HalpHorizontalResolution *
|
|
HalpVerticalResolution) / sizeof(ULONG);
|
|
|
|
limit = 0x100000/sizeof(ULONG); // mogawa
|
|
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 TRUE;
|
|
|
|
} //end of HalpDisplayPpcP91Setup
|
|
|
|
VOID
|
|
HalpDisplayCharacterP91 (
|
|
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') {
|
|
UCHAR DataByte;
|
|
DataByte = READ_REGISTER_UCHAR(((PCHAR)HalpVideoConfigBase)+65);
|
|
TRACE("Config[65]=0x%02x\n", DataByte);
|
|
|
|
HalpColumn = 0;
|
|
if (HalpRow < (HalpDisplayText - 1)) {
|
|
HalpRow += 1;
|
|
|
|
} else {
|
|
//RtlMoveMemory((PVOID)P91_VIDEO_MEMORY_BASE,
|
|
// (PVOID)(P91_VIDEO_MEMORY_BASE + HalpScrollLineP9),
|
|
// HalpScrollLengthP9);
|
|
|
|
// Scroll up one line
|
|
Destination = HalpP91VideoMemoryBase;
|
|
Source = (PUCHAR) HalpP91VideoMemoryBase + HalpScrollLine;
|
|
for (Index = 0; Index < HalpScrollLength; Index++) {
|
|
*Destination++ = *Source++;
|
|
}
|
|
// Blue the bottom line
|
|
Destination = HalpP91VideoMemoryBase + 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;
|
|
HalpOutputCharacterP91((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HalpOutputCharacterP91(
|
|
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) {
|
|
HalpDisplayCharacterP91('\n');
|
|
}
|
|
|
|
//
|
|
// Output the specified character and update the x cursor position.
|
|
//
|
|
|
|
Destination = (PUCHAR)(HalpP91VideoMemoryBase +
|
|
(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));
|
|
}
|
|
|
|
Glyph += 1;
|
|
for (J = 0; J < HalpCharacterWidth ; J += 1) {
|
|
if (FontValue >> 31 != 0) {
|
|
*Destination = 0xFF; //Make this pixel white
|
|
HalSweepDcacheRange(Destination, 1); // Push it out
|
|
}
|
|
Destination++;
|
|
//*Destination++ = (FontValue >> 31) ^ 1;
|
|
FontValue <<= 1;
|
|
}
|
|
|
|
Destination +=
|
|
(HalpHorizontalResolution - HalpCharacterWidth);
|
|
}
|
|
|
|
HalpColumn += 1;
|
|
return;
|
|
}
|
|
|
|
BOOLEAN
|
|
HalpDisplayPpcP91BlankScreen (
|
|
VOID
|
|
)
|
|
{
|
|
PULONG buffer;
|
|
ULONG limit, index;
|
|
|
|
if (HalpP91VideoMemoryBase == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
buffer = (PULONG)HalpP91VideoMemoryBase;
|
|
limit = (HalpHorizontalResolution *
|
|
HalpVerticalResolution) / sizeof(ULONG);
|
|
|
|
limit = 0x100000/sizeof(ULONG); // mogawa
|
|
for (index = 0; index < limit; index += 1) {
|
|
*buffer++ = 0x00000000;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
//
|
|
// Cirrus Device Driver
|
|
//
|
|
|
|
// 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.
|
|
//
|
|
|
|
VOID
|
|
HalpDisplayCharacterCirrus (
|
|
IN UCHAR Character
|
|
)
|
|
{
|
|
|
|
//
|
|
// 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
|
|
HalpScrollScreen(1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// added tab processing
|
|
//
|
|
|
|
else if ( Character == '\t' ) // tab?
|
|
{
|
|
HalpColumn += TAB_SIZE;
|
|
HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
|
|
|
|
if ( HalpColumn >= COLS ) // tab beyond end of screen?
|
|
{
|
|
HalpColumn = 0; // next tab stop is 1st column
|
|
// of next line
|
|
|
|
if ( HalpRow >= (HalpDisplayText - 1) )
|
|
HalpScrollScreen( 1 );
|
|
else ++HalpRow;
|
|
}
|
|
}
|
|
else if (Character == '\r')
|
|
{
|
|
HalpColumn = 0;
|
|
}
|
|
else if (Character == 0x7f)
|
|
{ // DEL character
|
|
if (HalpColumn != 0)
|
|
{
|
|
HalpColumn -= 1;
|
|
HalpOutputCharacterCirrus(0);
|
|
HalpColumn -= 1;
|
|
}
|
|
else // do nothing
|
|
;
|
|
}
|
|
else if (Character >= 0x20)
|
|
{
|
|
// Auto wrap for 80 columns
|
|
// per line
|
|
if (HalpColumn >= COLS)
|
|
{
|
|
HalpColumn = 0;
|
|
if (HalpRow < (HalpDisplayText - 1))
|
|
{
|
|
HalpRow += 1;
|
|
}
|
|
else
|
|
{ // need to scroll up the screen
|
|
HalpScrollScreen(1);
|
|
}
|
|
}
|
|
HalpOutputCharacterCirrus(Character);
|
|
}
|
|
// skip the nonprintable character
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
|
|
VOID
|
|
HalpOutputCharacterCirrus (
|
|
IN UCHAR AsciiChar
|
|
)
|
|
{
|
|
PUCHAR Destination;
|
|
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 < COLS)
|
|
{
|
|
I = (HalpRow*HalpScrollLine+HalpColumn*2);
|
|
Destination = (PUCHAR)(CIRRUS_TEXT_MEM + I + HalpScreenStart);
|
|
WRITE_CIRRUS_VRAM(Destination, AsciiChar);
|
|
HalpColumn += 1;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine initializes the Cirrus CL-GD5430 graphics controller chip
|
|
//
|
|
|
|
static void updattr(IN int rg,IN unsigned char val)
|
|
{
|
|
inp(0x3da);
|
|
outportb(0x3c0,rg);
|
|
outportb(0x3c0,val);
|
|
outportb(0x3c0,((unsigned char)(rg | 0x20)));
|
|
}
|
|
|
|
|
|
static void set_ext_regs(IN int reg,IN unsigned char *p)
|
|
{
|
|
unsigned char index, data;
|
|
|
|
while (*p != 0xff)
|
|
{
|
|
index= *p++;
|
|
data= *p++;
|
|
setreg(reg,index,data);
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
HalpDisplayPpcCirrusSetup (
|
|
VOID
|
|
)
|
|
{
|
|
int i;
|
|
|
|
//DbgBreakPoint();
|
|
TRACE("HalpDisplayPpcCirrusSetup: starting.\n");
|
|
if (HalpVideoMemoryBase == NULL) {
|
|
TRACE("HalpDisplayPpcCirrusSetup: calling KePhase0MapIo(CIRRUS_VIDEO_MEMORY_BASE,0x400000).\n");
|
|
HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)CIRRUS_VIDEO_MEMORY_BASE, 0x400000); // 4 MB
|
|
} else {
|
|
TRACE("HalpVideoMemoryBase=0x%08x\n", HalpVideoMemoryBase);
|
|
}
|
|
|
|
//
|
|
// Assert synchronous reset while setting the clock mode
|
|
//
|
|
|
|
setreg(0x3c4,0,1); // assert synchronous reset
|
|
|
|
outportb(0x3c2,0x67);
|
|
|
|
for ( i = 0; i < 21; i++ ) updattr(i,attr3[i]);
|
|
|
|
setreg(0x3d4,0x11,0x20);
|
|
for ( i = 0; i < 32; i++ ) setreg(0x3d4,i,crtc3[i]);
|
|
|
|
for ( i = 0x00;i < 9; i++ ) setreg(0x3ce,i,graph3[i]);
|
|
|
|
for ( i = 0; i < 5; i++ ) setreg(0x3c4,i,seq3[i]);
|
|
|
|
set_ext_regs (0x3c4,eseq3);
|
|
set_ext_regs (0x3d4,ecrtc3);
|
|
set_ext_regs (0x3ce,egraph3);
|
|
set_ext_regs (0x3c0,eattr3);
|
|
|
|
//
|
|
// Load 8x16 font
|
|
//
|
|
|
|
load8x16();
|
|
|
|
//
|
|
// Load color palette
|
|
//
|
|
|
|
load_ramdac();
|
|
|
|
outportb(0x3c6,0xff);
|
|
|
|
//
|
|
// Reset Hidden color register
|
|
//
|
|
|
|
// inp(0x3c6);
|
|
// inp(0x3c6);
|
|
// inp(0x3c6);
|
|
// inp(0x3c6);
|
|
// outp(0x3c6,0x00);
|
|
|
|
//
|
|
// Screen blank
|
|
//
|
|
|
|
clear_text();
|
|
|
|
//
|
|
// Initialize the current display column, row, and ownership values.
|
|
//
|
|
|
|
HalpColumn = 0;
|
|
HalpRow = 0;
|
|
HalpDisplayWidth = COLS;
|
|
HalpDisplayText = ROWS;
|
|
HalpScrollLine = ONE_LINE;
|
|
HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
|
|
HalpDisplayOwnedByHal = TRUE;
|
|
HalpScreenStart = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
VOID HalpScrollCirrus(
|
|
IN UCHAR line
|
|
)
|
|
{
|
|
ULONG LogicalTarget, PhysicalTarget;
|
|
int i;
|
|
|
|
for (i=0; i < line; i++) {
|
|
|
|
HalpScreenStart = HalpScreenStart + ONE_LINE;
|
|
setreg(0x3d4,0xC, (UCHAR) (HalpScreenStart >> 9));
|
|
setreg(0x3d4,0xD, (UCHAR) ((HalpScreenStart >> 1) & 0xFF));
|
|
|
|
for (LogicalTarget = TWENTY_FOUR_LINES;
|
|
LogicalTarget < TWENTY_FIVE_LINES;
|
|
LogicalTarget += 2) {
|
|
PhysicalTarget = LogicalTarget + HalpScreenStart + CIRRUS_TEXT_MEM;
|
|
WRITE_CIRRUS_VRAM(PhysicalTarget, ' ' );
|
|
WRITE_CIRRUS_VRAM(PhysicalTarget+1, TEXT_ATTR );
|
|
}
|
|
}
|
|
}
|
|
|
|
static void clear_text(VOID)
|
|
{
|
|
unsigned long p;
|
|
|
|
//
|
|
// fill plane 0 and 1 with 0x20 and 0x1f
|
|
//
|
|
|
|
for (p = CIRRUS_TEXT_MEM;
|
|
p < CIRRUS_TEXT_MEM+TWENTY_FIVE_LINES;
|
|
p += 2)
|
|
{
|
|
WRITE_CIRRUS_VRAM(p, ' ');
|
|
WRITE_CIRRUS_VRAM(p+1, TEXT_ATTR);
|
|
}
|
|
}
|
|
|
|
static void load8x16(VOID)
|
|
{
|
|
int i, j;
|
|
PUCHAR address;
|
|
|
|
//
|
|
// load 8x16 font into plane 2
|
|
//
|
|
|
|
setreg(0x3c4,0x04,(seq3[4] | 0x04));
|
|
|
|
//
|
|
// disable video and enable all to cpu to enable maximum video
|
|
// memory access
|
|
//
|
|
|
|
setreg(0x3c4,0x01,seq3[1] | 0x20);
|
|
setreg(0x3c4,2,4);
|
|
|
|
setreg(0x3ce,0x05,graph3[5] & 0xef);
|
|
setreg(0x3ce,0x06,0x05);
|
|
|
|
|
|
//
|
|
// fill plane 2 with 8x16 font
|
|
|
|
address = (void *) (CIRRUS_FONT_MEM);
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
for ( j = 0; j < 16; j++ )
|
|
{
|
|
WRITE_CIRRUS_VRAM(address,VGAFont8x16[i*16+j]);
|
|
address++;
|
|
}
|
|
|
|
for ( j = 16; j < 32; j++ )
|
|
{
|
|
WRITE_CIRRUS_VRAM(address,0);
|
|
address++;
|
|
}
|
|
}
|
|
|
|
setreg(0x3c4,0x01,seq3[1]);
|
|
setreg(0x3c4,0x04,seq3[4]);
|
|
setreg(0x3c4,2,seq3[2]);
|
|
|
|
setreg(0x3ce,0x06,graph3[6]);
|
|
setreg(0x3ce,0x05,graph3[5]);
|
|
}
|
|
|
|
|
|
static void load_ramdac()
|
|
{
|
|
int ix,j;
|
|
|
|
for ( ix = 0,j = 0; j <= 0x0FF ; ix = ix+3,j++ )
|
|
{
|
|
outp(0x3c8,(unsigned char)j); // write ramdac index
|
|
outp(0x3c9,TextPalette[ix]); // write red
|
|
outp(0x3c9,TextPalette[ix+1]); // write green
|
|
outp(0x3c9,TextPalette[ix+2]); // write blue
|
|
}
|
|
}
|
|
|