/*++ 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()