681 lines
20 KiB
C
681 lines
20 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1993, 1994 Weitek Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
p9100.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the code specific to the Weitek P9100.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History may be found at the end of this file.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "p9.h"
|
|||
|
#include "p9gbl.h"
|
|||
|
#include "p91regs.h"
|
|||
|
#include "vga.h"
|
|||
|
#include "wtkp9xvl.h"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
InitP9100(
|
|||
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize the P9100.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
VideoDebugPrint((2, "InitP9100------\n"));
|
|||
|
|
|||
|
P9_WR_REG(P91_INTERRUPT_EN, 0x00000080L); //INTERRUPT-EN = disabled
|
|||
|
P9_WR_REG(P91_PREHRZC, 0x00000000L); //PREHRZC = 0
|
|||
|
P9_WR_REG(P91_PREVRTC, 0x00000000L); //PREVRTC = 0
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the P9100 registers.
|
|||
|
//
|
|||
|
P9_WR_REG(P91_RFPERIOD, 0x00000186L); //RFPERIOD =
|
|||
|
P9_WR_REG(P91_RLMAX, 0x000000FAL); //RLMAX =
|
|||
|
P9_WR_REG(P91_DE_PMASK, 0xFFFFFFFFL); //allow writing in all 8 planes
|
|||
|
P9_WR_REG(P91_DE_DRAW_MODE, P91_WR_INSIDE_WINDOW | P91_DE_DRAW_BUFF_0);
|
|||
|
P9_WR_REG(P91_PE_W_OFF_XY, 0x00000000L); //disable any co-ord offset
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
P91_WriteTiming(
|
|||
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initializes the P9100 Crtc timing registers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
int num, den, bpp;
|
|||
|
ULONG ulValueRead, ulValueWritten;
|
|||
|
ULONG ulHRZSR;
|
|||
|
ULONG ulHRZBR;
|
|||
|
ULONG ulHRZBF;
|
|||
|
ULONG ulHRZT;
|
|||
|
|
|||
|
VideoDebugPrint((2, "P91_WriteTiming - Entry\n"));
|
|||
|
|
|||
|
bpp = HwDeviceExtension->usBitsPixel / 8; // Need bytes per pixel
|
|||
|
|
|||
|
//
|
|||
|
// 24-bit color
|
|||
|
//
|
|||
|
|
|||
|
if (bpp == 3)
|
|||
|
{
|
|||
|
num = 3;
|
|||
|
den = HwDeviceExtension->Dac.usRamdacWidth/8;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
num = 1;
|
|||
|
den = HwDeviceExtension->Dac.usRamdacWidth/(bpp * 8);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Calculate HRZSR.
|
|||
|
//
|
|||
|
ulHRZSR = (ULONG) (HwDeviceExtension->VideoData.hsyncp /
|
|||
|
(ULONG) den) * (ULONG) num;
|
|||
|
|
|||
|
ulHRZSR -= HwDeviceExtension->p91State.ulBlnkDlyAdj;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate HRZBR.
|
|||
|
//
|
|||
|
ulHRZBR = (ULONG) ((HwDeviceExtension->VideoData.hsyncp +
|
|||
|
HwDeviceExtension->VideoData.hbp) / (ULONG) den) *
|
|||
|
(ULONG) num;
|
|||
|
|
|||
|
ulHRZBR -= HwDeviceExtension->p91State.ulBlnkDlyAdj;
|
|||
|
|
|||
|
// ulHRZBR -= 4;
|
|||
|
|
|||
|
ulHRZBF = (ULONG) ( (HwDeviceExtension->VideoData.hsyncp+
|
|||
|
HwDeviceExtension->VideoData.hbp+
|
|||
|
HwDeviceExtension->VideoData.XSize) / (ULONG) den) * (ULONG) num;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate HRZBF.
|
|||
|
//
|
|||
|
ulHRZBF -= HwDeviceExtension->p91State.ulBlnkDlyAdj;
|
|||
|
|
|||
|
// ulHRZBF -= 4;
|
|||
|
|
|||
|
ulHRZT = (ULONG) ( (HwDeviceExtension->VideoData.hsyncp+
|
|||
|
HwDeviceExtension->VideoData.hbp+
|
|||
|
HwDeviceExtension->VideoData.XSize+
|
|||
|
HwDeviceExtension->VideoData.hfp) /
|
|||
|
(ULONG) den) * (ULONG) num;
|
|||
|
--ulHRZT;
|
|||
|
|
|||
|
//
|
|||
|
// Changes requested by Rober Embry, Jan 26 Spec.
|
|||
|
//
|
|||
|
|
|||
|
if (HwDeviceExtension->Dac.ulDacId == DAC_ID_BT489)
|
|||
|
{
|
|||
|
//
|
|||
|
// Fix for fussy screen problem, Per Sam Jenson
|
|||
|
//
|
|||
|
ulHRZT = 2 * (ulHRZT>>1) + 1;
|
|||
|
}
|
|||
|
|
|||
|
if ((HwDeviceExtension->Dac.ulDacId == DAC_ID_BT489) ||
|
|||
|
(HwDeviceExtension->Dac.ulDacId == DAC_ID_BT485))
|
|||
|
{
|
|||
|
if (bpp == 1)
|
|||
|
{
|
|||
|
ulHRZBR -= 12 * num / den;
|
|||
|
ulHRZBF -= 12 * num / den;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ulHRZBR -= 9 * num / den;
|
|||
|
ulHRZBF -= 9 * num / den;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// By robert embry 12/1/94
|
|||
|
//
|
|||
|
// The hardware configuration (Power 9100 version and DAC type) affects
|
|||
|
// the minimum horizontal back porch timing that a board can support.
|
|||
|
// The most flexible (able to support the smallest back porch)
|
|||
|
// configuration is with Power 9100 A4 with the IBM or ATT DAC.
|
|||
|
//
|
|||
|
// The Power 9100 A2 increases the front porch minimum by one.
|
|||
|
// The Brooktree DAC increases the front porch minimum by one, also.
|
|||
|
//
|
|||
|
// Configuration Min. Back Porch
|
|||
|
// ----------------- ---------------
|
|||
|
// P9100 A4, IBM/ATT DAC 40 pixels (5 CRTC clocks)
|
|||
|
// P9100 A2, IBM/ATT DAC 48 pixels (6 CRTC clocks)
|
|||
|
// P9100 A4, BT485/9 DAC 48 pixels (6 CRTC clocks)
|
|||
|
// P9100 A2, BT485/9 DAC 56 pixels (7 CRTC clocks)
|
|||
|
//
|
|||
|
// Since we want one P9x00RES.DAT file AND we don't want to penalize the
|
|||
|
// most common configuration, the driver needs to choose the best fit
|
|||
|
// when the P9x00RES.DAT file specifies a set of parameters that are not
|
|||
|
// supported.
|
|||
|
//
|
|||
|
// Algorithm for BEST FIT:
|
|||
|
//
|
|||
|
// First, time must be taken from something else. Either by shortening
|
|||
|
// the pulse width or the front porch (shifts line to right.) The
|
|||
|
// largest value of the two is decreased, sync pulse if equal.
|
|||
|
//
|
|||
|
// A given P9x00RES.DAT file will result in valid register values
|
|||
|
// in one hardware configuration, but not in another. This code
|
|||
|
// adjusts these register values so the P9x00RES.DAT file parameters
|
|||
|
// work for all boards, but not necesarily giving the requested timing.
|
|||
|
// The P9100 A4 silicon with an IBM or ATT DAC is the best case.
|
|||
|
// When the P9100 A2 or a Brooktree DAC is present then the
|
|||
|
// minimum supportable horizontal back porch is enlarged.
|
|||
|
//
|
|||
|
// psuedo BASIC code:
|
|||
|
//
|
|||
|
// This is parameter checking code for the Power 9100's hrzSR and hrzBR
|
|||
|
// registers. The following equation must be satisfied: hrzSR < hrzBR.
|
|||
|
//
|
|||
|
// If this equation is violated in the presence of the Power 9100 A2
|
|||
|
// silicon or a non-pipelined DAC (BT485/9) then these register values
|
|||
|
// are modified.
|
|||
|
//
|
|||
|
// This code should go just before the registers are written.
|
|||
|
// The register values may need to be modified by up to 2 counts.
|
|||
|
//
|
|||
|
// IF (DacType=BT485 OR DacType=BT485A OR DacType=BT489 OR _
|
|||
|
// SiliconVerion=A2) THEN {
|
|||
|
// WHILE hrzSR >= hrzBR {
|
|||
|
// IF hsp>hfp THEN DECR hrzSR _ ;shrink sync pulse width
|
|||
|
// ELSE INCR hrzBR :INCR hrzBF ;shorten front porch
|
|||
|
// } }
|
|||
|
//
|
|||
|
if ((HwDeviceExtension->Dac.ulDacId == DAC_ID_BT489) ||
|
|||
|
(HwDeviceExtension->Dac.ulDacId == DAC_ID_BT485) ||
|
|||
|
(HwDeviceExtension->p91State.usRevisionID < WTK_9100_REV3))
|
|||
|
{
|
|||
|
while (ulHRZSR >= ulHRZBR)
|
|||
|
{
|
|||
|
if (HwDeviceExtension->VideoData.hsyncp >
|
|||
|
HwDeviceExtension->VideoData.hfp)
|
|||
|
{
|
|||
|
ulHRZSR--;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ulHRZBR++;
|
|||
|
ulHRZBF++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Write to the video timing registers
|
|||
|
//
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_HRZSR, ulHRZSR);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_HRZSR);
|
|||
|
} while (ulValueRead != ulHRZSR);
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_HRZBR, ulHRZBR);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_HRZBR);
|
|||
|
} while (ulValueRead != ulHRZBR);
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_HRZBF, ulHRZBF);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_HRZBF);
|
|||
|
} while (ulValueRead != ulHRZBF);
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_HRZT, ulHRZT);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_HRZT);
|
|||
|
} while (ulValueRead != ulHRZT);
|
|||
|
|
|||
|
ulValueWritten = (ULONG) HwDeviceExtension->VideoData.vsp;
|
|||
|
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_VRTSR, ulValueWritten);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_VRTSR);
|
|||
|
} while (ulValueRead != ulValueWritten);
|
|||
|
|
|||
|
ulValueWritten = (ULONG) HwDeviceExtension->VideoData.vsp+
|
|||
|
HwDeviceExtension->VideoData.vbp;
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_VRTBR, ulValueWritten);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_VRTBR);
|
|||
|
} while (ulValueRead != ulValueWritten);
|
|||
|
|
|||
|
ulValueWritten = (ULONG) HwDeviceExtension->VideoData.vsp+
|
|||
|
HwDeviceExtension->VideoData.vbp+
|
|||
|
HwDeviceExtension->VideoData.YSize;
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_VRTBF, ulValueWritten);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_VRTBF);
|
|||
|
} while (ulValueRead != ulValueWritten);
|
|||
|
|
|||
|
ulValueWritten = (ULONG) HwDeviceExtension->VideoData.vsp+
|
|||
|
HwDeviceExtension->VideoData.vbp+
|
|||
|
HwDeviceExtension->VideoData.YSize+
|
|||
|
HwDeviceExtension->VideoData.vfp;
|
|||
|
do
|
|||
|
{
|
|||
|
P9_WR_REG(P91_VRTT, ulValueWritten);
|
|||
|
ulValueRead = (ULONG) P9_RD_REG(P91_VRTT);
|
|||
|
} while (ulValueRead != ulValueWritten);
|
|||
|
|
|||
|
VideoDebugPrint((2, "P91_WriteTiming - Exit\n"));
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // End of P91_WriteTimings()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
P91_SysConf(
|
|||
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Syscon converts the ->XSize value into the correct bits in
|
|||
|
the System Configuration Register and writes the register
|
|||
|
(This register contains the XSize of the display.)
|
|||
|
|
|||
|
Half-word and byte swapping are set via bits: 12 & 13;
|
|||
|
The shift control fields are set to the size of the scanline in bytes;
|
|||
|
And pixel size is set to bits per pixel.
|
|||
|
|
|||
|
XSize and ulFrameBufferSize must be set prior to entering this routine.
|
|||
|
This routine also initializes the clipping registers.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
int i, j, iBytesPerPixel; // loop counters
|
|||
|
long sysval; // swap bytes and words for little endian PC
|
|||
|
int xtem = (int) HwDeviceExtension->VideoData.XSize;
|
|||
|
long ClipMax; // clipping register value for NotBusy to restore
|
|||
|
|
|||
|
iBytesPerPixel = (int) HwDeviceExtension->usBitsPixel / 8; // Calc Bytes/pixel
|
|||
|
xtem *= iBytesPerPixel;
|
|||
|
|
|||
|
VideoDebugPrint((2, "P91_SysConf------\n"));
|
|||
|
|
|||
|
//
|
|||
|
// The following sets up the System Configuration Register
|
|||
|
// for BPP with byte and half-word swapping. This swapping
|
|||
|
// is usually what is needed since the frame-buffer is stored
|
|||
|
// in big endian pixel format and the 80x86 software usually
|
|||
|
// expects little endian pixel format.
|
|||
|
//
|
|||
|
if (iBytesPerPixel == 1)
|
|||
|
sysval = SYSCFG_BPP_8;
|
|||
|
else if (iBytesPerPixel == 2)
|
|||
|
sysval = SYSCFG_BPP_16;
|
|||
|
else if (iBytesPerPixel == 3)
|
|||
|
sysval = SYSCFG_BPP_24;
|
|||
|
else // if (iBytesPerPixel == 4)
|
|||
|
sysval = SYSCFG_BPP_32;
|
|||
|
|
|||
|
//
|
|||
|
// Now set the Shift3, Shift0, Shift1 & Shift2 multipliers.
|
|||
|
//
|
|||
|
// Each field in the sysconfig can only set a limited
|
|||
|
// range of bits in the size.
|
|||
|
//
|
|||
|
|
|||
|
if (xtem & 0x1c00) // 7168
|
|||
|
{
|
|||
|
//
|
|||
|
// Look at all the bits for shift control 3
|
|||
|
//
|
|||
|
j=3;
|
|||
|
for (i=4096;i>=1024;i>>=1)
|
|||
|
{
|
|||
|
//
|
|||
|
// If this bit is on...
|
|||
|
//
|
|||
|
if (i & xtem)
|
|||
|
{
|
|||
|
//
|
|||
|
// Use this field to set it and
|
|||
|
// remove the bit from the size. Each
|
|||
|
// field can only set one bit.
|
|||
|
//
|
|||
|
sysval |= ((long)j)<<29;
|
|||
|
xtem &= ~i;
|
|||
|
break;
|
|||
|
}
|
|||
|
j=j-1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (xtem & 0xf80) // each field in the sysconreg can only set
|
|||
|
{ // a limited range of bits in the size
|
|||
|
j = 7; // each field is 3 bits wide
|
|||
|
//
|
|||
|
// Look at all the bits for shift control 0
|
|||
|
//
|
|||
|
for (i = 2048; i >= 128;i >>= 1) // look at all the bits field 3 can effect
|
|||
|
{
|
|||
|
if (i & xtem) // if this bit is on,
|
|||
|
{
|
|||
|
sysval |= ((long) j) << 20; // use this field to set it
|
|||
|
xtem &= ~i; // and remove the bit from the size
|
|||
|
break; // each field can only set one bit
|
|||
|
}
|
|||
|
j -= 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (xtem & 0x7C0) // do the same thing for field 2
|
|||
|
{
|
|||
|
//
|
|||
|
// Do the same thing for shift control 1
|
|||
|
//
|
|||
|
j = 6; // each field is 3 bits wide
|
|||
|
for (i = 1024; i >= 64; i >>= 1) // look at all the bits field 2 can effect
|
|||
|
{
|
|||
|
if (i & xtem) // if this bit is on,
|
|||
|
{
|
|||
|
sysval |= ((long)j)<<17; // use this field to set it
|
|||
|
xtem &= ~i; // and remove the bit from the size
|
|||
|
break; // each field can only set one bit
|
|||
|
}
|
|||
|
j -= 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (xtem & 0x3E0) // do the same thing for field 1
|
|||
|
{
|
|||
|
j = 5; // each field is 3 bits wide
|
|||
|
//
|
|||
|
// do the same thing for shift control 2
|
|||
|
//
|
|||
|
for (i = 512; i >= 32;i >>= 1) // look at all the bits field 1 can effect
|
|||
|
{
|
|||
|
if (i & xtem) // if this bit is on,
|
|||
|
{
|
|||
|
sysval |= ((long) j) << 14; // use this field to set it
|
|||
|
xtem &= ~i; // and remove the bit from the size
|
|||
|
break; // each field can only set one bit
|
|||
|
}
|
|||
|
j -= 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If there are bits left, it is an illegal x size. This just means
|
|||
|
// that we cannot handle it because we have not implemented a
|
|||
|
// full multiplier. However, the vast majority of screen sizes can be
|
|||
|
// expressed as a sum of few powers of two.
|
|||
|
//
|
|||
|
if (xtem != 0) // if there are bits left, it is an
|
|||
|
return; // illegal x size.
|
|||
|
|
|||
|
VideoDebugPrint((2, "P91_SysConf:sysval = 0x%lx\n", sysval));
|
|||
|
|
|||
|
P9_WR_REG(P91_SYSCONFIG, sysval); // send data to the register
|
|||
|
|
|||
|
xtem = (int) (HwDeviceExtension->VideoData.XSize * (ULONG) iBytesPerPixel);
|
|||
|
//
|
|||
|
// Now calculate and set the max clipping to allow access to all of
|
|||
|
// the extra memory.
|
|||
|
//
|
|||
|
// There are two sets of clipping registers. The first takes the
|
|||
|
// horizontal diemnsion in pixels and the vertical dimension in
|
|||
|
// scanlines.
|
|||
|
//
|
|||
|
ClipMax=((long) HwDeviceExtension->VideoData.XSize - 1L) << 16 |
|
|||
|
(div32(HwDeviceExtension->FrameLength, (USHORT) xtem) - 1L);
|
|||
|
|
|||
|
P9_WR_REG(P91_DE_P_W_MIN, 0L);
|
|||
|
P9_WR_REG(P91_DE_P_W_MAX, ClipMax);
|
|||
|
|
|||
|
//
|
|||
|
// The second set takes the horizontal dimension in bytes and the
|
|||
|
// vertical dimension in scanlines.
|
|||
|
//
|
|||
|
ClipMax=((long) xtem -1L) << 16 |
|
|||
|
(div32(HwDeviceExtension->FrameLength, (USHORT) xtem) - 1L); // calc and set max
|
|||
|
|
|||
|
P9_WR_REG(P91_DE_B_W_MIN, 0L);
|
|||
|
P9_WR_REG(P91_DE_B_W_MAX, ClipMax);
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // End of P91_SysConf()
|
|||
|
|
|||
|
#define RESTORE_DAC 1
|
|||
|
//#define SAVE_INDEX_REGS 1
|
|||
|
/***************************************************************************\
|
|||
|
* *
|
|||
|
* Save & Restore VGA registers routines *
|
|||
|
* *
|
|||
|
* this is to avoid "blind" boot end *
|
|||
|
* *
|
|||
|
\***************************************************************************/
|
|||
|
|
|||
|
void P91SaveVGARegs(PHW_DEVICE_EXTENSION HwDeviceExtension,VGA_REGS * SaveVGARegisters)
|
|||
|
{
|
|||
|
UCHAR ucIndex ;
|
|||
|
ULONG ulIndex ;
|
|||
|
UCHAR temp;
|
|||
|
|
|||
|
#ifdef SAVE_INDEX_REGS
|
|||
|
// Save index registers.
|
|||
|
|
|||
|
temp = VGA_RD_REG(0x004);
|
|||
|
VideoDebugPrint((1, "Save, 3c4:%x\n", temp));
|
|||
|
|
|||
|
temp = VGA_RD_REG(0x00e);
|
|||
|
VideoDebugPrint((1, "Save, 3ce:%x\n", temp));
|
|||
|
|
|||
|
temp = VGA_RD_REG(0x014);
|
|||
|
VideoDebugPrint((1, "Save, 3d4:%x\n", temp));
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
/* Miscellaneous Output Register: [3C2]w, [3CC]r */
|
|||
|
SaveVGARegisters->MiscOut = VGA_RD_REG(0x00C) ;
|
|||
|
|
|||
|
/* CRT Controller Registers 0-18: index [3D4], data [3D5] */
|
|||
|
for (ucIndex = 0 ; ucIndex < 0x18 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x014 ,ucIndex) ;
|
|||
|
SaveVGARegisters->CR[ucIndex] = VGA_RD_REG(0x015) ;
|
|||
|
}
|
|||
|
|
|||
|
/* Sequencer Registers 1-4: index [3C4], data [3C5] */
|
|||
|
for (ucIndex = 1 ; ucIndex < 4 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x004 ,ucIndex) ;
|
|||
|
SaveVGARegisters->SR[ucIndex] = VGA_RD_REG(0x005) ;
|
|||
|
}
|
|||
|
|
|||
|
/* Graphics Controller Registers 0-8: index [3CE], data [3CF] */
|
|||
|
for (ucIndex = 0 ; ucIndex < 8 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x00E ,ucIndex) ;
|
|||
|
SaveVGARegisters->GR[ucIndex] = VGA_RD_REG(0x00F) ;
|
|||
|
}
|
|||
|
|
|||
|
/* Attribute Controller Registers 0-14: index and data [3C0]w, [3C1]r */
|
|||
|
VGA_RD_REG(0x01A) ; /* set toggle to index mode */
|
|||
|
for (ucIndex = 0 ; ucIndex < 0x14 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x000 ,ucIndex) ; /* write index */
|
|||
|
SaveVGARegisters->AR[ucIndex] = VGA_RD_REG(0x001) ; /* read data */
|
|||
|
VGA_WR_REG(0x000 ,SaveVGARegisters->AR[ucIndex]) ; /* toggle */
|
|||
|
}
|
|||
|
|
|||
|
#ifdef RESTORE_DAC
|
|||
|
//Look-Up Table: Read Index [3C7]w, Write Index [3C8], Data [3C9]
|
|||
|
VGA_WR_REG(0x007 ,0) ; //set read index to 0
|
|||
|
for (ulIndex = 0 ; ulIndex < (3 * 256) ; ulIndex ++)
|
|||
|
{
|
|||
|
SaveVGARegisters->LUT[ulIndex] = VGA_RD_REG(0x009) ;
|
|||
|
}
|
|||
|
#endif //RESTORE_DAC
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void P91RestoreVGAregs(PHW_DEVICE_EXTENSION HwDeviceExtension,VGA_REGS * SaveVGARegisters)
|
|||
|
{
|
|||
|
UCHAR ucIndex ;
|
|||
|
ULONG ulIndex ;
|
|||
|
UCHAR temp;
|
|||
|
|
|||
|
WriteP9ConfigRegister(HwDeviceExtension,P91_CONFIG_MODE,0x2);
|
|||
|
/* Put the VGA back in color mode for our PROM */
|
|||
|
VGA_WR_REG(MISCOUT ,1) ;
|
|||
|
|
|||
|
/* Enable VGA Registers: [3C3] = 1 */
|
|||
|
VGA_WR_REG(0x003 ,1) ;
|
|||
|
|
|||
|
/* Miscellaneous Output Register: [3C2]w, [3CC]r */
|
|||
|
VGA_WR_REG(0x002 ,SaveVGARegisters->MiscOut) ;
|
|||
|
|
|||
|
/* Enable CR0-CR7: CR11[7] = 0 */
|
|||
|
VGA_WR_REG(0x014 ,0x11) ;
|
|||
|
VGA_WR_REG(0x015 ,SaveVGARegisters->CR[0x11] & 0x7F) ;
|
|||
|
|
|||
|
/* CRT Controller Registers 0-18: index [3D4], data [3D5] */
|
|||
|
for (ucIndex = 0 ; ucIndex < 0x18 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x014 ,ucIndex) ;
|
|||
|
VGA_WR_REG(0x015 ,SaveVGARegisters->CR[ucIndex]) ;
|
|||
|
}
|
|||
|
|
|||
|
/* Synchronous Reset: SR0 = 1 */
|
|||
|
VGA_WR_REG(0x004 ,0) ;
|
|||
|
VGA_WR_REG(0x005 ,1) ;
|
|||
|
|
|||
|
/* ClockMode: SR1 */
|
|||
|
VGA_WR_REG(0x004 ,1) ;
|
|||
|
VGA_WR_REG(0x005 ,SaveVGARegisters->SR[1]) ;
|
|||
|
|
|||
|
/* Non Reset Mode: SR0 = 0 */
|
|||
|
VGA_WR_REG(0x004 ,0) ;
|
|||
|
VGA_WR_REG(0x005 ,0) ;
|
|||
|
|
|||
|
/* Sequencer Registers 2-4: index [3C4], data [3C5] */
|
|||
|
for (ucIndex = 2 ; ucIndex < 4 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x004 ,ucIndex) ;
|
|||
|
VGA_WR_REG(0x005 ,SaveVGARegisters->SR[ucIndex]) ;
|
|||
|
}
|
|||
|
|
|||
|
/* Graphics Controller Regs 0-8: index [3CE], data [3CF] */
|
|||
|
VGA_WR_REG(0x00E ,1) ;
|
|||
|
VGA_WR_REG(0x00F ,0x0F) ; /* enable all 4 planes for GR0 */
|
|||
|
for (ucIndex = 0 ; ucIndex < 8 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x00E ,ucIndex) ;
|
|||
|
VGA_WR_REG(0x00F ,SaveVGARegisters->GR[ucIndex]) ;
|
|||
|
}
|
|||
|
|
|||
|
/* Attrib Controller Regs 0-14:index and data [3C0]w,[3C1]r */
|
|||
|
VGA_RD_REG(0x01A) ; /* set toggle to index mode */
|
|||
|
for (ucIndex = 0 ; ucIndex < 0x14 ; ucIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x000 ,ucIndex) ; /* write index */
|
|||
|
VGA_WR_REG(0x000 ,SaveVGARegisters->AR[ucIndex]) ;
|
|||
|
/* write data */
|
|||
|
}
|
|||
|
VGA_WR_REG(0x000 ,0x20) ; /* set index[5] to 1 */
|
|||
|
|
|||
|
#ifdef SAVE_INDEX_REGS
|
|||
|
// Restore index registers.
|
|||
|
|
|||
|
VGA_WR_REG(0x004, 0x002);
|
|||
|
temp = VGA_RD_REG(0x004);
|
|||
|
VideoDebugPrint((1, "Restore: 3c4:%x\n", temp));
|
|||
|
|
|||
|
VGA_WR_REG(0x00e, 0x005);
|
|||
|
temp = VGA_RD_REG(0x00e);
|
|||
|
VideoDebugPrint((1, "Restore: 3ce:%x\n", temp));
|
|||
|
|
|||
|
VGA_WR_REG(0x014, 0x0011);
|
|||
|
temp = VGA_RD_REG(0x014);
|
|||
|
VideoDebugPrint((1, "Restore: 3d4:%x\n", temp));
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef RESTORE_DAC
|
|||
|
|
|||
|
//Look-Up Table:
|
|||
|
//Read Index [3C7]w, Write Index [3C8], Data [3C9]
|
|||
|
VGA_WR_REG(0x008 ,0) ; // set write index to 0
|
|||
|
for (ulIndex = 0 ; ulIndex < (3 * 256) ; ulIndex ++)
|
|||
|
{
|
|||
|
VGA_WR_REG(0x009 ,SaveVGARegisters->LUT[ulIndex]) ;
|
|||
|
}
|
|||
|
#endif //RESTORE_DAC
|
|||
|
}
|