mirror of https://github.com/tongzx/nt5src
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.
988 lines
29 KiB
988 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 1993, 1994 Weitek Corporation
|
|
|
|
Module Name:
|
|
|
|
p91supp.c
|
|
|
|
Abstract:
|
|
|
|
This module contains functions for calculating memconf and srtcrl values
|
|
for the Weitek P9 miniport device driver.
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History may be found at the end of this file.
|
|
|
|
--*/
|
|
|
|
#include "p9.h"
|
|
#include "p9gbl.h"
|
|
#include "p91regs.h"
|
|
|
|
|
|
extern VOID
|
|
ProgramClockSynth(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
USHORT usFrequency,
|
|
BOOLEAN bSetMemclk,
|
|
BOOLEAN bUseClockDoubler
|
|
);
|
|
|
|
//
|
|
// Local function Prototypes
|
|
//
|
|
|
|
VOID
|
|
CalcP9100MemConfig (
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|
);
|
|
|
|
VOID
|
|
P91SizeVideoMemory(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|
);
|
|
|
|
BOOLEAN
|
|
P91TestVideoMemory(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
USHORT iNumLongWords
|
|
);
|
|
|
|
ULONG
|
|
Logbase2(
|
|
ULONG ulValue
|
|
);
|
|
|
|
|
|
VOID
|
|
CalcP9100MemConfig (
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Calculate the value to be stored in the Power 9100 memory configuration
|
|
field as well as the srtctl field.
|
|
|
|
Argumentss:
|
|
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension.
|
|
|
|
Return Values:
|
|
|
|
FALSE - If the operation is not successful.
|
|
TRUE - If the operation is successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN fDacDividesClock;
|
|
USHORT usShiftClockIndex;
|
|
USHORT usSrtctlSrcIncIndex;
|
|
USHORT usLoadClock;
|
|
USHORT usDivisionFactor;
|
|
USHORT usClkFreqIndex;
|
|
USHORT usBlankDlyIndex;
|
|
USHORT usSamIndex;
|
|
USHORT usDacWidthIndex;
|
|
USHORT usNumBanksIndex;
|
|
USHORT usEffectiveBackendBanks;
|
|
USHORT usDepthOfOneSAM;
|
|
USHORT usEffectiveSAMDepth;
|
|
USHORT usEffectiveRowDepth;
|
|
USHORT usMemClkInUse;
|
|
|
|
ULONG ulMemConfig;
|
|
ULONG ulSrtCtl;
|
|
|
|
//
|
|
// Define the positive (rising edge) blank delay index table for when the
|
|
// Power 9100 is dividing the clock.
|
|
//
|
|
USHORT usPositiveBlnkDly[2][2][3] =
|
|
{
|
|
//
|
|
// Define blank delay for 128K deep VRAM
|
|
// 1Bnk 2Bnk 4Bnk
|
|
//
|
|
{
|
|
{0xFF, 0x00, 0x00}, // 32-Bit RAMDAC
|
|
{0xFF, 0x00, 0x00} // 64-Bit RAMDAC
|
|
},
|
|
|
|
//
|
|
// Define blank delay for 256K deep VRAM
|
|
// 1Bnk 2Bnk 4Bnk
|
|
//
|
|
{
|
|
{0x01, 0x02, 0x00}, // 32-Bit RAMDAC
|
|
{0xFF, 0x01, 0x02} // 64-Bit RAMDAC
|
|
}
|
|
};
|
|
|
|
//
|
|
// Define the negative (falling edge) blank delay index table for when the
|
|
// Power 9100 is dividing the clock.
|
|
//
|
|
USHORT usNegativeBlnkDly[2][2][3] =
|
|
{
|
|
//
|
|
// Define blank delay for 128K deep VRAM
|
|
// 1Bnk 2Bnk 4Bnk
|
|
//
|
|
{
|
|
{0xFF, 0x02, 0x03}, // 32-Bit RAMDAC
|
|
{0xFF, 0x01, 0x02} // 64-Bit RAMDAC
|
|
},
|
|
|
|
//
|
|
// Define blank delay for 256K deep VRAM
|
|
// 1Bnk 2Bnk 4Bnk
|
|
//
|
|
{
|
|
{0x01, 0x02, 0x03}, // 32-Bit RAMDAC
|
|
{0xFF, 0x01, 0x02} // 64-Bit RAMDAC
|
|
}
|
|
};
|
|
|
|
//
|
|
// Define the VRAM configuration mem_config.config lookup table.
|
|
//
|
|
ULONG ulMemConfTable[] =
|
|
{
|
|
0,
|
|
P91_MC_CNFG_1,
|
|
0,
|
|
P91_MC_CNFG_3,
|
|
P91_MC_CNFG_4,
|
|
P91_MC_CNFG_5,
|
|
0,
|
|
P91_MC_CNFG_7,
|
|
0,
|
|
0,
|
|
0,
|
|
P91_MC_CNFG_11,
|
|
0,
|
|
0,
|
|
P91_MC_CNFG_14,
|
|
P91_MC_CNFG_15
|
|
};
|
|
|
|
//
|
|
// Define the mem_config.shiftclk_mode and mem_config.soe_mode lookup table.
|
|
//
|
|
ULONG ulShiftClockMode[] =
|
|
{
|
|
P91_MC_SHFT_CLK_1_BANK | P91_MC_SERIAL_OUT_1_BANK,
|
|
P91_MC_SHFT_CLK_2_BANK | P91_MC_SERIAL_OUT_2_BANK,
|
|
P91_MC_SHFT_CLK_4_BANK | P91_MC_SERIAL_OUT_4_BANK
|
|
};
|
|
|
|
//
|
|
// Define the mem_config.shiftclk_freq and mem_config.crtc_freq lookup table.
|
|
//
|
|
ULONG ulClockFreq[] =
|
|
{
|
|
P91_MC_SHFT_CLK_DIV_1 | P91_MC_CRTC_CLK_DIV_1,
|
|
P91_MC_SHFT_CLK_DIV_2 | P91_MC_CRTC_CLK_DIV_2,
|
|
P91_MC_SHFT_CLK_DIV_4 | P91_MC_CRTC_CLK_DIV_4,
|
|
P91_MC_SHFT_CLK_DIV_8 | P91_MC_CRTC_CLK_DIV_8,
|
|
P91_MC_SHFT_CLK_DIV_16 | P91_MC_CRTC_CLK_DIV_16
|
|
};
|
|
|
|
//
|
|
// Define the mem_config.blank_dly field lookup table.
|
|
//
|
|
ULONG ulBlankDly[] =
|
|
{
|
|
P91_MC_BLNKDLY_0_CLK,
|
|
P91_MC_BLNKDLY_1_CLK,
|
|
P91_MC_BLNKDLY_2_CLK,
|
|
P91_MC_BLNKDLY_3_CLK
|
|
};
|
|
|
|
//
|
|
// Define the srtctl.src_incs field lookup table.
|
|
//
|
|
ULONG ulSrtctlSrcInc[] =
|
|
{
|
|
P91_SRTCTL_SRC_INC_256,
|
|
P91_SRTCTL_SRC_INC_512,
|
|
P91_SRTCTL_SRC_INC_1024
|
|
};
|
|
|
|
//
|
|
// A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
|
|
//
|
|
// First initialize the memory clock that is being used. This value may
|
|
// need to be changed if it is determined that the conditions are right
|
|
// for the split shift transfer bug to occur.
|
|
//
|
|
// First choose the default value for the clock being used just in case
|
|
// there was not a value passed in.
|
|
//
|
|
usMemClkInUse = (HwDeviceExtension->p91State.usRevisionID ==
|
|
WTK_9100_REV1) ? DEF_P9100_REV1_MEMCLK :
|
|
DEF_P9100_MEMCLK;
|
|
|
|
//
|
|
// A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
|
|
//
|
|
// Now select either the default memory clock or the value passed in.
|
|
//
|
|
// usMemClkInUse = (*pusMemClock) ? *pusMemClock : usMemClkInUse;
|
|
|
|
//
|
|
// Initialize the constant fields of the Screen Repaint Timing Control
|
|
// register value.
|
|
//
|
|
ulSrtCtl = P91_SRTCTL_DISP_BUFF_0 | // display_buffer (3)
|
|
P91_SRTCTL_HR_NORMAL | // hblnk_relaod (4)
|
|
P91_SRTCTL_ENABLE_VIDEO | // enable_video (5)
|
|
P91_SRTCTL_HSYNC_INT | // internal_hsync (7)
|
|
P91_SRTCTL_VSYNC_INT; // internal_vsync (8)
|
|
|
|
//
|
|
// Initialize the memory configuration fields to start things off.
|
|
//
|
|
|
|
ulMemConfig = ulMemConfTable[HwDeviceExtension->p91State.usMemConfNum];
|
|
|
|
//
|
|
// Initialize all of the constant fields.
|
|
//
|
|
ulMemConfig |= P91_MC_MISS_ADJ_1 | // vram_miss_adj (3)
|
|
P91_MC_READ_ADJ_1 | // vram_read_adj (4)
|
|
P91_MC_WRITE_ADJ_1 | // vram_write_adj (5)
|
|
P91_MC_VCP_PRIORITY_HI | // priority_select (6)
|
|
P91_MC_DAC_ACCESS_ADJ_0 | // dac_access_adj (7)
|
|
P91_MC_DAC_MODE_0 | // dac_mode (8)
|
|
P91_MC_MEM_VID_NORMAL | // hold_reset (9)
|
|
P91_MC_MUXSEL_NORMAL | // reserved (16-17)
|
|
P91_MC_SLOW_HOST_ADJ_1 | // slow_host_hifc (30)
|
|
P91_MC_READ_SMPL_ADJ_1; // vram_read_sample (31)
|
|
|
|
//
|
|
// Calculate the number of effective back-end banks in the current configuration. This
|
|
// value is used to calculate several fields in the memory configuration register.
|
|
//
|
|
usEffectiveBackendBanks = (32*HwDeviceExtension->p91State.usNumVramBanks)
|
|
/ HwDeviceExtension->Dac.usRamdacWidth;
|
|
|
|
//
|
|
// Determine the depth of one shift register as follows:
|
|
// 128k deep VRAM has a row size of 256 => depth of one shift register is 256
|
|
// 256k deep VRAM has a row size of 512 => depth of one shift register is 512
|
|
//
|
|
usDepthOfOneSAM = (HwDeviceExtension->p91State.ulPuConfig &
|
|
P91_PUC_128K_VRAMS) ? 256 : 512;
|
|
|
|
//
|
|
// Calculate the effective SAM and Row depths. These values are used to calculate the
|
|
// initial value for the SRTCTL register.
|
|
//
|
|
usEffectiveSAMDepth = usDepthOfOneSAM * usEffectiveBackendBanks;
|
|
usEffectiveRowDepth = usDepthOfOneSAM *
|
|
HwDeviceExtension->p91State.usNumVramBanks;
|
|
|
|
//
|
|
// Calculate the index into the Shift Clock Mode lookup table. The index is calculated
|
|
// as Logbase2(usEffectiveBakendBanks) should give either a 0, 1 or 2.
|
|
//
|
|
usShiftClockIndex = usEffectiveBackendBanks >> 1;
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: usEffectiveBackendBanks = %d\n",
|
|
usEffectiveBackendBanks));
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: usShiftClockIndex = %d\n",
|
|
usShiftClockIndex));
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: usShiftClockMode[] = %lx\n",
|
|
ulShiftClockMode[usShiftClockIndex]));
|
|
//
|
|
// Now, using the Shift Clock Mode lookup table index, set both the shiftclk_mode (22-23)
|
|
// and soe_mode (24-25) fields.
|
|
//
|
|
ulMemConfig |= ulShiftClockMode[usShiftClockIndex];
|
|
|
|
switch (HwDeviceExtension->p91State.ulPuConfig & P91_PUC_VRAM_SAM_SIZE)
|
|
{
|
|
case P91_PUC_FULL_SIZE_SHIFT:
|
|
{
|
|
//
|
|
// Calculate the initial value for the SRTCTL register.
|
|
//
|
|
// First set srtctl.src_incs...
|
|
//
|
|
usSrtctlSrcIncIndex = (USHORT) (Logbase2 ((ULONG) usEffectiveRowDepth) - 9);
|
|
ulSrtCtl |= ulSrtctlSrcInc[usSrtctlSrcIncIndex];
|
|
|
|
//
|
|
// And then srtctl.qsfselect
|
|
//
|
|
ulSrtCtl |= Logbase2((ULONG) usEffectiveSAMDepth) - 5;
|
|
|
|
//
|
|
// Set the vad_shft field for full size SAMs.
|
|
//
|
|
ulMemConfig |= P91_MC_VAD_DIV_1;
|
|
|
|
break;
|
|
}
|
|
|
|
case P91_PUC_HALF_SIZE_SHIFT:
|
|
{
|
|
//
|
|
// Calculate the initial value for the SRTCTL register.
|
|
//
|
|
// First set srtctl.src_incs...
|
|
//
|
|
usSrtctlSrcIncIndex = (USHORT) (Logbase2 ((ULONG) usEffectiveRowDepth) - 9);
|
|
|
|
if (usSrtctlSrcIncIndex)
|
|
{
|
|
//
|
|
// For half size SAMs, if src_incs is not already equal to 0 then it will get
|
|
// decremented by one...
|
|
//
|
|
--usSrtctlSrcIncIndex;
|
|
ulSrtCtl |= ulSrtctlSrcInc[usSrtctlSrcIncIndex];
|
|
|
|
//
|
|
// And vad_shft will be set to 0.
|
|
//
|
|
ulMemConfig |= P91_MC_VAD_DIV_1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If src_incs is already equal to 0, then it will be left as is...
|
|
//
|
|
ulSrtCtl |= ulSrtctlSrcInc[usSrtctlSrcIncIndex];
|
|
|
|
//
|
|
// And vad_shft will be set to 1.
|
|
//
|
|
ulMemConfig |= P91_MC_VAD_DIV_2;
|
|
}
|
|
|
|
//
|
|
// Now set srtctl.qsfselect for half size SAMs.
|
|
//
|
|
ulSrtCtl |= Logbase2 ((ULONG) usEffectiveSAMDepth) - 6;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine if the RAMDAC should divide the clock.
|
|
//
|
|
|
|
usLoadClock = (USHORT) ((HwDeviceExtension->VideoData.dotfreq1 /
|
|
HwDeviceExtension->Dac.usRamdacWidth) *
|
|
HwDeviceExtension->usBitsPixel);
|
|
|
|
// start of non-JEDEC memory bug fix
|
|
|
|
if (
|
|
(HwDeviceExtension->p91State.usRevisionID < WTK_9100_REV3) &&
|
|
(HwDeviceExtension->usBitsPixel <= 16) &&
|
|
( ( (HwDeviceExtension->p91State.usNumVramBanks == 2) &&
|
|
(HwDeviceExtension->Dac.usRamdacWidth == 64) &&
|
|
((HwDeviceExtension->p91State.ulPuConfig &
|
|
P91_PUC_FREQ_SYNTH_TYPE) != P91_PUC_FIXED_MEMCLK) &&
|
|
(usLoadClock < 1200)
|
|
) ||
|
|
( usLoadClock < 800 )
|
|
)
|
|
#ifdef _MIPS_
|
|
&& !( HwDeviceExtension->MachineType == SIEMENS_P9100_VLB
|
|
|| HwDeviceExtension->MachineType == SIEMENS_P9100_PCi)
|
|
// SNI-Od: 22-1-96:
|
|
// hum!! (HwDeviceExtension->Dac.usRamdacID != DAC_ID_IBM525) ??
|
|
#endif
|
|
)
|
|
{
|
|
if (HwDeviceExtension->VideoData.dotfreq1 <= 6750 )
|
|
{
|
|
ulMemConfig |= ((2 - (HwDeviceExtension->usBitsPixel/8) +
|
|
(HwDeviceExtension->Dac.usRamdacWidth/32)) << 10) // shiftclk_freq (10-12)
|
|
|
|
|
((2 - (HwDeviceExtension->usBitsPixel/8) +
|
|
(HwDeviceExtension->Dac.usRamdacWidth/32)) << 13); // crtc_freq (13-15)
|
|
}
|
|
else
|
|
{
|
|
ulMemConfig |= ((1 - (HwDeviceExtension->usBitsPixel/8) +
|
|
(HwDeviceExtension->Dac.usRamdacWidth/32)) << 10) // shiftclk_freq (10-12)
|
|
|
|
|
((1 - (HwDeviceExtension->usBitsPixel/8) +
|
|
(HwDeviceExtension->Dac.usRamdacWidth/32)) << 13); // crtc_freq (13-15)
|
|
}
|
|
fDacDividesClock = FALSE;
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
|
|
//
|
|
// This is the main logic for the split shift transfer bug software work
|
|
// around. The current assumption is that the RAMDAC will always be doing
|
|
// the dividing of the clock.
|
|
//
|
|
fDacDividesClock = TRUE;
|
|
|
|
//
|
|
// A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
|
|
//
|
|
// Special attention is required for A1/A2 silicon for low resolution modes
|
|
// such as 640x480x8, 640x480x15, 640x480x16 and 800x600x8. Furthormore,
|
|
// the problem only occurs on boards with 2 megabytes of VRAM, a 64-bit
|
|
// RAMDAC and when the following condition is met.
|
|
//
|
|
// (SCLK * 7) < MEMCLK
|
|
//
|
|
// Note: The value calculated for LCLK can also be used in place of SCLK
|
|
// in the computations.
|
|
//
|
|
if ((HwDeviceExtension->p91State.usRevisionID < WTK_9100_REV3) &&
|
|
(HwDeviceExtension->usBitsPixel != 24) &&
|
|
((HwDeviceExtension->p91State.ulPuConfig &
|
|
P91_PUC_MEMORY_DEPTH) == P91_PUC_256K_VRAMS) &&
|
|
(HwDeviceExtension->p91State.usNumVramBanks == 2) &&
|
|
(HwDeviceExtension->Dac.usRamdacWidth == 64) &&
|
|
((HwDeviceExtension->p91State.ulPuConfig &
|
|
P91_PUC_FREQ_SYNTH_TYPE) != P91_PUC_FIXED_MEMCLK) &&
|
|
((usLoadClock * 7) < usMemClkInUse))
|
|
{
|
|
//
|
|
// All the conditions are right for the split shift transfer bug to occur.
|
|
// The software fix for this bug requires that the memory clock is adjusted
|
|
// so that the (SCLK * 7) < MEMCLK equation is no longer satisfied. This is
|
|
// done easily enough by setting MEMCLK = SCLK * 7. By doing this, MEMCLK is
|
|
// not reduced any more than neccessary.
|
|
//
|
|
usMemClkInUse = (usLoadClock * 7);
|
|
}
|
|
//
|
|
// Reprogram MEMCLK...
|
|
//
|
|
ProgramClockSynth(HwDeviceExtension, usMemClkInUse, TRUE, FALSE);
|
|
|
|
//
|
|
// A1/A2 silicon SPLIT SHIFT TRANSFER BUG FIX
|
|
//
|
|
// Because of the current work around, the RAMDAC always does the dividing of
|
|
// of the clock and the DDOTCLK is always used, so set those bit here.
|
|
//
|
|
// Set the shiftclk_freq (10-12), crtc_freq (13-15) and video_clk_sel (20) fields for
|
|
// when the RAMDAC is dividing the clock.
|
|
//
|
|
ulMemConfig |= P91_MC_SHFT_CLK_DIV_1 | // shiftclk_freq (10-12)
|
|
P91_MC_CRTC_CLK_DIV_1 | // crtc_freq (13-15)
|
|
P91_MC_VCLK_SRC_DDOTCLK; // video_clk_sel (20)
|
|
|
|
}
|
|
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: usLoadClock = %d\n",
|
|
usLoadClock));
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: fDacDividesClock = %d\n",
|
|
fDacDividesClock));
|
|
|
|
#if 0
|
|
|
|
if (fDacDividesClock)
|
|
{
|
|
//
|
|
// Set the shiftclk_freq (10-12), crtc_freq (13-15) and video_clk_sel (20) fields for
|
|
// when the RAMDAC is dividing the clock.
|
|
//
|
|
ulMemConfig |= P91_MC_SHFT_CLK_DIV_1 | // shiftclk_freq (10-12)
|
|
P91_MC_CRTC_CLK_DIV_1 | // crtc_freq (13-15)
|
|
P91_MC_VCLK_SRC_DDOTCLK; // video_clk_sel (20)
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set the shiftclk_freq (10-12), crtc_freq (13-15) and video_clk_sel (20) fields for
|
|
// when the Power 9100 is dividing the clock.
|
|
//
|
|
usDivisionFactor = (USHORT) (HwDeviceExtension->Dac.usRamdacWidth /
|
|
HwDeviceExtension->usBitsPixel);
|
|
usClkFreqIndex = (USHORT) Logbase2 ((ULONG) usDivisionFactor);
|
|
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: usClkFreqIndex#1 = %d\n",
|
|
usClkFreqIndex));
|
|
|
|
if (HwDeviceExtension->VideoData.dotfreq1 >
|
|
HwDeviceExtension->Dac.ulMaxClkFreq) // was if (usFreqRatio == 2)
|
|
{
|
|
--usClkFreqIndex;
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: usClkFreqIndex#2 = %d\n",
|
|
usClkFreqIndex));
|
|
}
|
|
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: usClkFreqIndex = %d\n",
|
|
usClkFreqIndex));
|
|
VideoDebugPrint((2, "CalcP9100MemConfig: ulClockFreq[] = %lx\n",
|
|
ulClockFreq[usClkFreqIndex]));
|
|
|
|
ulMemConfig |= ulClockFreq[usClkFreqIndex];
|
|
|
|
//
|
|
// video_clk_sel is always PIXCLK when the 9100 is dividing the clock.
|
|
//
|
|
ulMemConfig |= P91_MC_VCLK_SRC_PIXCLK;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Determine the setting for the blank_edge (19) field
|
|
//
|
|
if ((usLoadClock <= 3300) ||
|
|
(HwDeviceExtension->p91State.usRevisionID >= WTK_9100_REV3))
|
|
{
|
|
ulMemConfig |= P91_MC_SYNC_FALL_EDGE;
|
|
}
|
|
else
|
|
{
|
|
ulMemConfig |= P91_MC_SYNC_RISE_EDGE;
|
|
}
|
|
|
|
//
|
|
// Do the magic for the blank_dly (27-28) field.
|
|
//
|
|
|
|
if (HwDeviceExtension->p91State.usRevisionID >= WTK_9100_REV3)
|
|
{
|
|
//
|
|
// For A3 silicon, this is simply a 1.
|
|
//
|
|
usBlankDlyIndex = 1;
|
|
|
|
//
|
|
// Now special case for the number of banks and the DAC width.
|
|
//
|
|
|
|
if ((HwDeviceExtension->p91State.usNumVramBanks == 4) &&
|
|
(HwDeviceExtension->Dac.usRamdacWidth == 32))
|
|
{
|
|
++usBlankDlyIndex;
|
|
}
|
|
}
|
|
else if (fDacDividesClock)
|
|
{
|
|
//
|
|
// When not on A3 and the DAC is dividing the clock, there's a little
|
|
// more to this field.
|
|
//
|
|
if ((ulMemConfig & P91_MC_BLANK_EDGE_MSK) == P91_MC_SYNC_RISE_EDGE)
|
|
{
|
|
usBlankDlyIndex = 1;
|
|
}
|
|
else
|
|
{
|
|
usBlankDlyIndex = 2;
|
|
}
|
|
|
|
//
|
|
// Now special case for the number of banks and the DAC width.
|
|
//
|
|
if ((HwDeviceExtension->p91State.usNumVramBanks == 4) &&
|
|
(HwDeviceExtension->Dac.usRamdacWidth == 32))
|
|
{
|
|
++usBlankDlyIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// When the Power 9100 is dividing the clock this gets really messy.
|
|
//
|
|
usSamIndex = ((HwDeviceExtension->p91State.ulPuConfig &
|
|
P91_PUC_VRAM_SAM_SIZE) == P91_PUC_FULL_SIZE_SHIFT) ? 1 : 0;
|
|
|
|
usDacWidthIndex = (HwDeviceExtension->Dac.usRamdacWidth / 32) - 1;
|
|
|
|
usNumBanksIndex = HwDeviceExtension->p91State.usNumVramBanks >> 1;
|
|
|
|
if ((ulMemConfig & P91_MC_BLANK_EDGE_MSK) == P91_MC_SYNC_RISE_EDGE)
|
|
{
|
|
usBlankDlyIndex = usPositiveBlnkDly[usSamIndex]
|
|
[usDacWidthIndex]
|
|
[usNumBanksIndex];
|
|
}
|
|
else
|
|
{
|
|
usBlankDlyIndex = usNegativeBlnkDly[usSamIndex]
|
|
[usDacWidthIndex]
|
|
[usNumBanksIndex];
|
|
}
|
|
|
|
//
|
|
// Now special case for the number of banks, the DAC width, the SAM size and
|
|
// the pixel depth.
|
|
//
|
|
if ((HwDeviceExtension->usBitsPixel == 32) &&
|
|
(HwDeviceExtension->p91State.usNumVramBanks == 1) &&
|
|
(usSamIndex == 1) &&
|
|
(HwDeviceExtension->Dac.usRamdacWidth == 32))
|
|
{
|
|
usBlankDlyIndex = 2;
|
|
}
|
|
|
|
if ((HwDeviceExtension->usBitsPixel == 32) &&
|
|
(HwDeviceExtension->p91State.usNumVramBanks == 2) &&
|
|
(usSamIndex == 1) &&
|
|
(HwDeviceExtension->Dac.usRamdacWidth == 32))
|
|
{
|
|
usBlankDlyIndex = 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now use the blank delay index to set the blank_dly (27-38) field in the
|
|
// memory configuration regsiter.
|
|
//
|
|
ulMemConfig |= ulBlankDly[usBlankDlyIndex];
|
|
|
|
//
|
|
// Now calculate the blank delay adjustment used when calculating the timing
|
|
// values.
|
|
//
|
|
HwDeviceExtension->p91State.ulBlnkDlyAdj = (ULONG) usBlankDlyIndex;
|
|
|
|
//
|
|
// As if everything wasn't bad enough!!! One more special case.
|
|
//
|
|
if ((HwDeviceExtension->p91State.usRevisionID >= WTK_9100_REV3) &&
|
|
(HwDeviceExtension->p91State.usNumVramBanks == 2) &&
|
|
((HwDeviceExtension->p91State.ulPuConfig & P91_PUC_VRAM_SAM_SIZE)
|
|
== P91_PUC_HALF_SIZE_SHIFT) &&
|
|
(HwDeviceExtension->Dac.usRamdacWidth == 64) &&
|
|
(HwDeviceExtension->usBitsPixel == 8) &&
|
|
(HwDeviceExtension->VideoData.XSize == 640) &&
|
|
(HwDeviceExtension->VideoData.YSize == 480))
|
|
{
|
|
//
|
|
// Fix up for A3 silicon.
|
|
//
|
|
HwDeviceExtension->p91State.ulBlnkDlyAdj++;
|
|
}
|
|
|
|
//
|
|
// Set the return values.
|
|
//
|
|
HwDeviceExtension->p91State.ulMemConfVal = ulMemConfig;
|
|
HwDeviceExtension->p91State.ulSrctlVal = ulSrtCtl;
|
|
HwDeviceExtension->Dac.bRamdacDivides = fDacDividesClock;
|
|
|
|
return;
|
|
|
|
} // End CalcP9100MemConfig ()
|
|
|
|
|
|
|
|
ULONG
|
|
Logbase2 (
|
|
ULONG ulValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calculates the LOG Base 2 of the passed in value.
|
|
|
|
Argumentss:
|
|
|
|
ulValue - Value to calculate LOG Base 2 for.
|
|
|
|
Return Values:
|
|
|
|
ulResult - LOG Base 2 of ulValue.
|
|
|
|
--*/
|
|
{
|
|
ULONG ulResult;
|
|
|
|
ulResult = 0;
|
|
while (ulValue != 1)
|
|
{
|
|
++ulResult;
|
|
ulValue >>= 1;
|
|
}
|
|
|
|
return (ulResult);
|
|
|
|
} // End of Logbase2()
|
|
|
|
|
|
BOOLEAN
|
|
P91TestVideoMemory(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
USHORT iNumLongWords
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Routine to check if our memory configuration is set right.
|
|
|
|
Argumentss:
|
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|
Specified number of longwords to test.
|
|
|
|
Return Values:
|
|
TRUE == if video memory checks out OK.
|
|
FALSE == otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
unsigned long i;
|
|
|
|
ULONG ulOtherBankBits;
|
|
ULONG aulOldBits[32];
|
|
|
|
BOOLEAN bRet = TRUE;
|
|
|
|
//
|
|
// The SandleFoot blue screen showed corruption from this test.
|
|
// We tried to not save this data, but we had to.
|
|
// In addition to saving the screen data around the test, we have also
|
|
// saved the state of the Memory Configuration register.
|
|
|
|
ulOtherBankBits =
|
|
VideoPortReadRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + 0x8000);
|
|
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
aulOldBits[i] =
|
|
VideoPortReadRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i);
|
|
}
|
|
|
|
//
|
|
// Make sure you cause a row change at the beginning of the memory
|
|
// by first accessing a location that is guaranteed to be in another row.
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + 0x8000,
|
|
0x5A5A5A5A);
|
|
|
|
//
|
|
// Test iNumLongWords doubleword locations by writing the inverse of the
|
|
// address to each memory location.
|
|
//
|
|
for (i = 0 ; i < iNumLongWords; i++)
|
|
{
|
|
VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i,
|
|
~i);
|
|
}
|
|
|
|
//
|
|
// Now read them back and test for failure
|
|
//
|
|
|
|
for (i = 0 ; i < iNumLongWords; i++)
|
|
{
|
|
//
|
|
// If any one fails, return error...
|
|
//
|
|
|
|
if (VideoPortReadRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i)
|
|
!= ~i)
|
|
{
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Restore everything.
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + 0x8000,
|
|
ulOtherBankBits);
|
|
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
VideoPortWriteRegisterUlong((PULONG) HwDeviceExtension->FrameAddress + i,
|
|
aulOldBits[i]);
|
|
}
|
|
|
|
//
|
|
// If all of them work, return success
|
|
//
|
|
|
|
return(bRet);
|
|
|
|
} // End of int P91TestVideoMemory()
|
|
|
|
|
|
VOID
|
|
P91SizeVideoMemory(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Routine to determine the amount of memory and what memory configuration
|
|
bits to set.
|
|
This routine assumes that the board is already initialized.
|
|
It also sets (...)
|
|
|
|
Argumentss:
|
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|
|
|
Return Values:
|
|
None.
|
|
|
|
Modifies:
|
|
HwDeviceExtension->p91State.usNumVramBanks = 1,2 or 4;
|
|
HwDeviceExtension->p91State.ulFrameBufferSize = 0x0100000,
|
|
0x0200000 or 0x0400000;
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ulMemConfig;
|
|
|
|
VideoDebugPrint((2, "P91SizeVideoMemory - Entry\n"));
|
|
|
|
|
|
ulMemConfig = P9_RD_REG(P91_MEM_CONFIG);
|
|
|
|
if (HwDeviceExtension->p91State.bVram256)
|
|
{
|
|
//
|
|
// Assume 4 banks and test assertion...
|
|
//
|
|
|
|
HwDeviceExtension->p91State.usMemConfNum = 7;
|
|
HwDeviceExtension->p91State.usNumVramBanks = 4;
|
|
HwDeviceExtension->p91State.ulFrameBufferSize = 0x0400000;
|
|
|
|
P9_WR_REG(P91_MEM_CONFIG, 0x00000007);
|
|
|
|
if (!P91TestVideoMemory(HwDeviceExtension, 32))
|
|
{
|
|
//
|
|
// Assertion failed, so assume 2 banks and test assertion...
|
|
//
|
|
|
|
HwDeviceExtension->p91State.usMemConfNum = 5;
|
|
HwDeviceExtension->p91State.usNumVramBanks = 2;
|
|
HwDeviceExtension->p91State.ulFrameBufferSize = 0x0200000L;
|
|
P9_WR_REG(P91_MEM_CONFIG, 0x00000005);
|
|
|
|
if (!P91TestVideoMemory(HwDeviceExtension, 32))
|
|
{
|
|
//
|
|
// If second assertion fails, assume 1 bank
|
|
//
|
|
|
|
HwDeviceExtension->p91State.usMemConfNum = 4;
|
|
HwDeviceExtension->p91State.usNumVramBanks = 1;
|
|
HwDeviceExtension->p91State.ulFrameBufferSize = 0x0100000;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Assume 4 banks and test assertion...
|
|
//
|
|
HwDeviceExtension->p91State.usMemConfNum = 3;
|
|
HwDeviceExtension->p91State.usNumVramBanks = 4;
|
|
HwDeviceExtension->p91State.ulFrameBufferSize = 0x0200000;
|
|
P9_WR_REG(P91_MEM_CONFIG, 0x00000003);
|
|
|
|
if (!P91TestVideoMemory(HwDeviceExtension, 32))
|
|
{
|
|
//
|
|
// Assertion failed, so assume 2 banks
|
|
//
|
|
|
|
HwDeviceExtension->p91State.usMemConfNum = 1;
|
|
HwDeviceExtension->p91State.usNumVramBanks = 2;
|
|
HwDeviceExtension->p91State.ulFrameBufferSize = 0x0100000L;
|
|
}
|
|
}
|
|
|
|
VideoDebugPrint((3, "P91SizeVideoMemory: usNumVramBanks = %d\n",
|
|
HwDeviceExtension->p91State.usNumVramBanks));
|
|
|
|
VideoDebugPrint((3, "P91SizeVideoMemory: usFrameBufferSize = %lx\n",
|
|
HwDeviceExtension->p91State.ulFrameBufferSize));
|
|
|
|
VideoDebugPrint((2, "P91SizeVideoMemory - Exit\n"));
|
|
|
|
P9_WR_REG(P91_MEM_CONFIG, ulMemConfig);
|
|
|
|
} // End of P91SizeVideoMemory()
|
|
|
|
|
|
BOOLEAN
|
|
ValidateMode(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
PVIDEO_MODE_INFORMATION ModeInformation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Function to determine if the mode is valid based on the current
|
|
adapter. The factors that determine if the mode is valid are the
|
|
DAC and the size of video ram.
|
|
|
|
Argumentss:
|
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|
ModeInformation - Pointer to the resolution information.
|
|
|
|
Return Values:
|
|
TRUE == The resolution is valid,
|
|
FALSE == The resolution is invalid.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Check to see if 24BPP mode is specified and if this DAC supports it...
|
|
//
|
|
if ( (ModeInformation->BitsPerPlane == 24) &&
|
|
(!HwDeviceExtension->Dac.bRamdac24BPP) )
|
|
return(FALSE); // 24Bpp not supported by this DAC...
|
|
|
|
//
|
|
// Check to see if we have enough video ram to support this resolution...
|
|
//
|
|
if ( ((ULONG) (ModeInformation->BitsPerPlane/8) *
|
|
ModeInformation->VisScreenWidth *
|
|
ModeInformation->VisScreenHeight) >
|
|
HwDeviceExtension->FrameLength )
|
|
{
|
|
VideoDebugPrint((2, "ValidateMode: VisScreenWidth = %d\n",
|
|
ModeInformation->VisScreenWidth));
|
|
VideoDebugPrint((2, "ValidateMode: VisScreenHeight = %d\n",
|
|
ModeInformation->VisScreenHeight));
|
|
VideoDebugPrint((2, "ValidateMode: BitsPerPlane = %d\n",
|
|
ModeInformation->BitsPerPlane));
|
|
VideoDebugPrint((2, "ValidateMode: Vram needed = %ld\n",
|
|
((ULONG) (ModeInformation->BitsPerPlane/8) *
|
|
ModeInformation->VisScreenWidth *
|
|
ModeInformation->VisScreenHeight) ));
|
|
return(FALSE); // Not enough video memory for this mode...
|
|
}
|
|
else
|
|
return(TRUE);
|
|
|
|
} // End of ValidateMode()
|