📄 ltcrt.c
字号:
DALDEBUG((DALDBG_NORMAL, "ATIRAGE.SYS! GDO-CRT: CRTIsDisplayPhysicallyConnected - Entry"));
// EPR 32286
// Try to talk to a DDC monitor first. If Edid is read from DDC CRT,
// then CRT is physically connected.
if(CRTEdidDetection(hGDO))
{
DALDEBUG((DALDBG_NORMAL, "ATIRAGE.SYS! GDO-CRT: A DDC CRT is detected."));
return TRUE;
}
//
// The monitor either wasn't connected or it is a non-DDC monitor.
// So, use software algorithm to handle CRT detection.
//
// Checks controller number. 0: primary, 1: Secondary
if ( hGDORageCRT->ulController == PRIMARY_CONTROLLER)
{
// Set LCD_DATA register to index 1( LCD_GEN_CTRL).
ulLCDIndex = MMREADULONG(hGDORageCRT->lpMMR, LCD_INDEX);
ulLCDIndex &= (~LCD_INDEX__LCD_REG_INDEX_MASK);
ulLCDIndex |= LCD_INDEX_lcdGenCtrlReg;
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_INDEX, ulLCDIndex);
// Read LCD GEN CTRL data from LCD data register first.
// set CRTC_RW_SELECT bit to 0 which makes register R/W go to
// primary CRTC, and turn on CRT.
ulLCDGenCtrlData = MMREADULONG(hGDORageCRT->lpMMR, LCD_DATA);
ulLCDGenCtrlData &= (~LCD_GEN_CTL_CrtcRWSelect);
ulLCDGenCtrlData |= LCD_GEN_CTRL__CRT_ON;
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_DATA, ulLCDGenCtrlData);
// enables the DAC compare which we will need later and
// select data source for the monitor (primary).
ulDACCntlData=
ulDACCntlTemp = MMREADULONG(hGDORageCRT->lpMMR, DAC_CNTL);
ulDACCntlTemp &= (~DAC_CNTL__DAC_CMP_DIS);
ulDACCntlTemp &= (~DAC_CNTL_Dac1ClkSel);
MMWRITEULONG(hGDORageCRT->lpMMR, DAC_CNTL, ulDACCntlTemp);
// Preserve CRTC_GEN_CNTL and enable Overscan in VGA.
ulCRTCGenCntlTemp =
ulCRTCGenCntlData = MMREADULONG(hGDORageCRT->lpMMR, CRTC_GEN_CNTL);
ulCRTCGenCntlTemp &= (~CRTC_GEN_CNTL_CrtcDisplayDis);
ulCRTCGenCntlTemp |= CRTC_GEN_CNTL_CrtcVgaXoverscan;
MMWRITEULONG(hGDORageCRT->lpMMR, CRTC_GEN_CNTL, ulCRTCGenCntlTemp);
} else {
// Set LCD_DATA register to index 1( LCD_GEN_CTRL).
ulLCDIndexData =
ulLCDIndex = MMREADULONG(hGDORageCRT->lpMMR, LCD_INDEX);
ulLCDIndex &= (~LCD_INDEX__LCD_REG_INDEX_MASK);
ulLCDIndex |= LCD_INDEX_lcdGenCtrlReg;
ulLCDIndex &= (~LCD_INDEX_Crtc2DisplayDis);
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_INDEX, ulLCDIndex);
// Read LCD GEN CTRL data from LCD data register first.
// set CRTC_RW_SELECT bit to 1 which makes register R/W go to
// secondary CRTC, and turn on CRT.
ulLCDGenCtrlData =
ulLCDGenCtrlTemp = MMREADULONG(hGDORageCRT->lpMMR, LCD_DATA);
ulLCDGenCtrlTemp |= (LCD_GEN_CTL_CrtcRWSelect | LCD_GEN_CTRL__CRT_ON);
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_DATA, ulLCDGenCtrlTemp);
// enables the DAC compare which we will need later and
// select data source for the monitor (secondary).
ulDACCntlData=
ulDACCntlTemp = MMREADULONG(hGDORageCRT->lpMMR, DAC_CNTL);
ulDACCntlTemp &= (~DAC_CNTL__DAC_CMP_DIS);
ulDACCntlTemp |= DAC_CNTL_Dac1ClkSel;
MMWRITEULONG(hGDORageCRT->lpMMR, DAC_CNTL, ulDACCntlTemp);
}
//
// Preserve Sequencer Data (Index 1) and allow CPU:CRT interleaved access
// to video memory.
//
MMWRITEUCHAR(hGDORageCRT->lpMMR, SEQUENCER_INDEX,
SEQUENCER_CLOCK_MODE, 0);
ucSequencerTemp =
ucSequencerData = MMREADUCHAR(hGDORageCRT->lpMMR, SEQUENCER_DATA, 0);
ucSequencerTemp &= (~SEQUENCER_CLOCK_MODE__SEQ_MAXBW);
MMWRITEUCHAR(hGDORageCRT->lpMMR, SEQUENCER_DATA, ucSequencerTemp, 0);
lMaxLines = MMREADULONG(hGDORageCRT->lpMMR, CRTC_V_TOTAL_DISP);
lMaxLines = ((lMaxLines & CRTC_V_TOTAL_DISP__CRTC_V_DISP_MASK)>>16);
ulOverTopBottom = MMREADULONG(hGDORageCRT->lpMMR, OVR_WID_TOP_BOTTOM);
ulOverClr = MMREADULONG(hGDORageCRT->lpMMR, OVR_CLR); //preserve Overscan color.
MMWRITEULONG(hGDORageCRT->lpMMR, OVR_CLR, CRT_DETECT_COLOR);
// If Overscan bottom width less than 2, write 2 to Overscan bottom width.
if ((ulOverTopBottom & 0x1FF0000) < 2 )
{
MMWRITEULONG(hGDORageCRT->lpMMR, OVR_WID_TOP_BOTTOM,
(ulOverTopBottom | 0x020000));
}
lCurrentLine = ( (MMREADULONG(hGDORageCRT->lpMMR, CRTC_CRNT_VLINE) &
CRTC_VLINE_CRNT_VLINE__CRTC_CRNT_VLINE_MASK) >> 16);
while (lCurrentLine != 0)
{
lCurrentLine = ( (MMREADULONG(hGDORageCRT->lpMMR, CRTC_CRNT_VLINE) &
CRTC_VLINE_CRNT_VLINE__CRTC_CRNT_VLINE_MASK) >> 16);
}
while (bInDACCntlLoop == FALSE)
{
lCurrentLine = ( (MMREADULONG(hGDORageCRT->lpMMR, CRTC_CRNT_VLINE) &
CRTC_VLINE_CRNT_VLINE__CRTC_CRNT_VLINE_MASK) >> 16);
while (lCurrentLine == (lMaxLines+2))
{
if ((MMREADULONG(hGDORageCRT->lpMMR, DAC_CNTL)) & DAC_CNTL__DAC_CMP_OUTPUT)
{
lOneCount++;
}
else
{
lZeroCount++;
}
lCurrentLine = ( (MMREADULONG(hGDORageCRT->lpMMR, CRTC_CRNT_VLINE) &
CRTC_VLINE_CRNT_VLINE__CRTC_CRNT_VLINE_MASK) >> 16);
bInDACCntlLoop = TRUE;
}// end while
}
// restore all the registers that we played with.
MMWRITEULONG(hGDORageCRT->lpMMR, DAC_CNTL, ulDACCntlData);
MMWRITEULONG(hGDORageCRT->lpMMR, OVR_CLR, ulOverClr);
MMWRITEULONG(hGDORageCRT->lpMMR, OVR_WID_TOP_BOTTOM, ulOverTopBottom);
MMWRITEUCHAR(hGDORageCRT->lpMMR, SEQUENCER_INDEX,
SEQUENCER_CLOCK_MODE, 0);
MMWRITEUCHAR(hGDORageCRT->lpMMR, SEQUENCER_DATA, ucSequencerData, 0);
if ( hGDORageCRT->ulController == PRIMARY_CONTROLLER)
{
// Set LCD_DATA register to index 1( LCD_GEN_CTRL).
ulLCDIndex = MMREADULONG(hGDORageCRT->lpMMR, LCD_INDEX);
ulLCDIndex &= (~LCD_INDEX__LCD_REG_INDEX_MASK);
ulLCDIndex |= LCD_INDEX_lcdGenCtrlReg;
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_INDEX, ulLCDIndex);
// Restore LCD GEN Control register
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_DATA, ulLCDGenCtrlData);
// Restore CRTC GEN Control register.
MMWRITEULONG(hGDORageCRT->lpMMR, CRTC_GEN_CNTL, ulCRTCGenCntlData);
}
else
{
// Set LCD_DATA register to index 1( LCD_GEN_CTRL).
ulLCDIndex = MMREADULONG(hGDORageCRT->lpMMR, LCD_INDEX);
ulLCDIndex &= (~LCD_INDEX__LCD_REG_INDEX_MASK);
ulLCDIndex |= LCD_INDEX_lcdGenCtrlReg;
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_INDEX, ulLCDIndex);
// Restore LCD GEN Control register
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_DATA, ulLCDGenCtrlData);
// Restore LCD Index register.
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_INDEX, ulLCDIndexData);
}
DALDEBUG((DALDBG_NORMAL, "ATIRAGE.SYS! GDO-CRT: Zero Count= %8x, One Count= %8x",lZeroCount, lOneCount));
// It is important to note here that although this algorthim seems
// to produce good results it can not be considered a 100% accurate
// way of determining CRT connectedness. It does seem to be the best
// algorithm in terms of detecting connectedness and minimizing visual
// artifacts.
if (lZeroCount < lOneCount)
{
DALDEBUG((DALDBG_NORMAL, "ATIRAGE.SYS! GDO-CRT: CRT is physically Connected (Software)"));
return (TRUE);
}
else
{
DALDEBUG((DALDBG_NORMAL, "ATIRAGE.SYS! GDO-CRT: CRT is not physically Connected (Software)"));
return(FALSE);
}
} // End CRTSoftwareDetection
/******************************Public*Routine******************************\
* EPR 32286
* BOOL FAR CRTEdidDetection(GDO hGDO)
*
* This function will call the NO-BIOS code to get partial EDID from DDC CRT.
* This feature can be used to decide if a DDC monitor is attached.
*
* Step 1. Read EDID through DVI.
* If EDID is read successfully and display type is CRT,
* then return TRUE. Otherwise, go to Step 2.
* Step 2. Read EDID through regular CRT connector.
*
\**************************************************************************/
BOOL FAR CRTEdidDetection(HGDO hGDO)
{
EDID_BUFFER EdidQueryBuffer;
LPGDO_RAGE_CRT hGDORageCRT;
hGDORageCRT = (LPGDO_RAGE_CRT)hGDO;
DALDEBUG((DALDBG_NORMAL, "ATIRAGE.SYS! GDO-CRT: CRTEdidDetection - Entry"));
//
// Read partial EDID through DVI and then check device type.
//
hGDORageCRT->bREADEDIDFROMDVI = TRUE;
if(DDC2DETQuery(hGDO, hGDORageCRT->hDDL,
(LPUCHAR)&EdidQueryBuffer.aucEdidDataBuffer))
{
// Check display type.
if( CRTEDIDCHECKDISPLAYTYPE(hGDO, hGDORageCRT->hDDL, (LPUCHAR)&EdidQueryBuffer.aucEdidDataBuffer)
== HW_DISPLAY_TYPE_CRT)
return TRUE;
}
//
// Read partial EDID through regular CRT connector.
//
hGDORageCRT->bREADEDIDFROMDVI = FALSE;
if( DDC2DETQuery(hGDO, hGDORageCRT->hDDL,
(LPUCHAR)&EdidQueryBuffer.aucEdidDataBuffer))
{
return TRUE;
}
// Fail to get Edid from CRT.
return FALSE;
}
/******************************Public*Routine******************************\
* VOID CRTDetectionImproved(HGDO hGDO)
*
* This routine assigns proper value to FORCE_DAC_DATA_SEL and
* FORCE_DAC_DATA to improve CRT detection.
*
\**************************************************************************/
VOID FAR
CRTDetectionImproved(HGDO hGDO)
{
ULONG ulLCDIndex;
ULONG ulLCDMiscCntlData;
LPGDO_RAGE_CRT hGDORageCRT;
hGDORageCRT = (LPGDO_RAGE_CRT)hGDO;
// Set LCD_DATA register to index 14( LCD_MISC_CNTL).
ulLCDIndex = MMREADULONG(hGDORageCRT->lpMMR, LCD_INDEX);
ulLCDIndex &= (~LCD_INDEX__LCD_REG_INDEX_MASK);
ulLCDIndex |= LCD_INDEX_LcdMiscCntl;
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_INDEX, ulLCDIndex);
// Read LCD MISC_CTRL data from LCD data register first.
ulLCDMiscCntlData = MMREADULONG(hGDORageCRT->lpMMR, LCD_DATA);
//
// Assign "11" to FORCE_DAC_DATA_SEL.
// Assign "52"(Hex) to FORCE_DAC_DATA.
//
ulLCDMiscCntlData &= (~LCD_MISC_CNTL__FORCE_DAC_DATA_SEL_MASK);
ulLCDMiscCntlData |= 0x00C00000;
ulLCDMiscCntlData &= (~LCD_MISC_CNTL__FORCE_DAC_DATA_MASK);
ulLCDMiscCntlData |= 0x52000000;
MMWRITEULONG(hGDORageCRT->lpMMR, LCD_DATA, ulLCDMiscCntlData);
} // End CRTDetectionImproved
/******************************Public*Routine******************************\
* BOOL CRTIsModeSupported(HGDO hGDO, LPDEVMODE_INFO lpMI, ULONG ulController)
*
* CRTIsModeSupported determines if the requsted mode is supported by the
* device.
*
\**************************************************************************/
BOOL FAR
CRTIsModeSupported(
HGDO hGDO,
LPDEVMODE_INFO lpMI,
ULONG ulController
)
{
DALDEBUG((DALDBG_ENTRY_EXIT, "ATIRAGE.SYS! GDO-CRT: CRTIsModeSupported - Entry"));
// some work obviously needs to be done here...
return(TRUE);
} // end CRTIsModeSupported
/******************************Public*Routine********************************\
* VOID CRTSetMode(HGDO hGDO,
* LPDEVMODE_INFO lpMI,
* ULONG ulController,
* PFNGDOTIMINGS pfnDalSetAdjustmentTimings,
* LPHANDLE lpParameter)
*
* CRTSetMode is called to allow the GDO to set up some default values for
* certain paramaters.
\****************************************************************************/
VOID FAR
CRTSetMode(HGDO hGDO,
LPDEVMODE_INFO lpMI,
ULONG ulController,
PFNDALTIMINGS pfnDalSetAdjustmentTimings,
LPHANDLE lpParameter
)
{
LPGDO_RAGE_CRT hGDORageCRT;
hGDORageCRT = (LPGDO_RAGE_CRT)hGDO;
DALDEBUG((DALDBG_NORMAL, "ATIRAGE.SYS! GDO-CRT: CRTSetMode - Entry"));
//Save adjustment function for later use
hGDORageCRT->pfnDalSetAdjustmentTimings = pfnDalSetAdjustmentTimings;
hGDORageCRT->lpParameter = lpParameter;
// fill in controller information. 0: Primary, otherwise: secondary.
hGDORageCRT->ulController = ulController;
} // end CRTSetMode
/******************************Public*Routine********************************\
* VOID CRTPreModeChange(HGDO hGDO,
* LPDEVMODE_INFO lpMI)
* GDOPreModeChange performs any pre-mode configuration required by
* the controller before a mode change occurs.
*
\****************************************************************************/
VOID FAR
CRTPreModeChange(HGDO hGDO,
LPDEVMODE_INFO lpMI
)
{
// there shouldn't be anything to do here...
}// CRTPreModeChange
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -