⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dalddc.c

📁 此代码为WCE5.0下显示器的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/****************************************************************************\
*
*  Module Name    dalddc.c
*  Project        ATI Display Abstraction Layer
*  Device         RageProPNP / Rage128 (Win95/98 & WinNT 4.0/5.0)
*
*  Description    source file for Display Abstraction Layer 0.87
*                 contains functions for processing DDC queries
*
*  Copyright (c) 1998-2000 ATI Technologies Inc. (unpublished)
*
*  All rights reserved.  This notice is intended as a precaution against
*  inadvertent publication and does not imply publication or any waiver
*  of confidentiality.  The year included in the foregoing notice is the
*  year of creation of the work.
*
*  Refer to DAL Developers Guide & Programming Reference Rev 0.87 for usage

\****************************************************************************/

#include "dal.h"
#include "daldef.h"
#include "dalddc.h"
#include "cwddedi.h"


  // Define structure passed as a context to DDC query callback function.
  //
typedef struct _DALDDC_DDCCONTEXT
{
  LPHW_DAL_EXTENSION  lpHDE;
  LPDEVGDO      lpDisplay;
  LPUCHAR       lpucQueryBuffer;
  ULONG         ulLength;           // Size if query buffer in bytes
  
} DALDDC_DDCCONTEXT, *LPDALDDC_DDCCONTEXT;



  // These are private functions implementing DDC. Declare them as static.
  //
static BOOL FilterEdidData    (LPEDID_BUFFER lpEDIDBuf);
static BOOL DDCQuery  (LPHW_DAL_EXTENSION lpHDE, LPDEVGDO lpDisplay,
                       LPEDID_BUFFER lpEDIDBuf);
static BOOL DDCQueryCallback (LPDALDDC_DDCCONTEXT lpddcContext);
static BOOL DDCStart  (LPDEVGDO lpDisplay);
static BOOL DDCStop   (LPDEVGDO lpDisplay);
static BOOL DDCRead   (LPDEVGDO lpDisplay, LPUCHAR  lpucBuf, ULONG ulLen, UCHAR ucReadAddr);
static BOOL DDCWrite  (LPDEVGDO lpDisplay, LPUCHAR  lpucBuf, ULONG ulLen);
static BOOL DDCReadByte (LPDEVGDO lpDisplay, LPUCHAR  lpucByte, BOOL bMore);
static BOOL DDCWriteByte  (LPDEVGDO lpDisplay,  UCHAR ucByte);
static BOOL DDCWaitForClockLineHigh (LPDEVGDO lpDisplay);


  //
  // Allow swapping.
  //
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(PAGE_DDC, bIsDisplayDDCPhysicallyConnected)
#pragma alloc_text(PAGE_DDC, bGetEdidData)
#pragma alloc_text(PAGE_DDC, GetStandardEdidLength)
#pragma alloc_text(PAGE_DDC, GetDisplayTypeFromEdid)
#pragma alloc_text(PAGE_DDC, FilterEdidData)
#pragma alloc_text(PAGE_DDC, DDCQuery)
#pragma alloc_text(PAGE_DDC, DDCQueryCallback)
#pragma alloc_text(PAGE_DDC, DDCStart)
#pragma alloc_text(PAGE_DDC, DDCStop)
#pragma alloc_text(PAGE_DDC, DDCRead)
#pragma alloc_text(PAGE_DDC, DDCWrite)
#pragma alloc_text(PAGE_DDC, DDCReadByte)
#pragma alloc_text(PAGE_DDC, DDCWriteByte)
#pragma alloc_text(PAGE_DDC, DDCWaitForClockLineHigh)
#endif  // defined (ALLOC_PRAGMA)

/******************************Public*Routine******************************\
* BOOL bUseDalBasedDdc(LPDEVGDO lpDisplay)
*
* Check whether GDO supports DDC queries (old style GDO) (1) or it supports 
* additional hooks allowing for DDC implementation in DAL (2).
*   (1) : Must export GetEdidData hook
*   (2) : Must export DDCReadLine, DDCWriteLine instead of GetEdidData;
*         Can export SetNextDisplayConnector if supports multiple connectors;
*         Optioanally may export PreDDCQuery, PostDDCQuery;
* Return FALSE for (1) and TRUE for (2)
*
\**************************************************************************/

BOOL 
bUseDalBasedDdc(
  LPDEVGDO      lpDisplay)
{
  if ((GDO_HOOK2_DDCREADLINE | GDO_HOOK2_DDCWRITELINE)
      == (lpDisplay->lpHWED->ulFunctionHooks2 &
      (GDO_HOOK2_DDCREADLINE | GDO_HOOK2_DDCWRITELINE)))
  {
      // Assert the old DDC GetEdidData hook is not exported. Not fatal.
      //
    DALASSERT(!(lpDisplay->lpHWED->ulFunctionHooks & GDO_HOOK_GET_EDID_DATA),
              "Old GetEdidData hook ignored");

    return TRUE;
  }
  else
  {   // Try to use the old style GetEdidData hook (it can be still missing)

      // Assert there are no any new DDC hooks. This is not fatal.
      //
    DALASSERT(0 == (lpDisplay->lpHWED->ulFunctionHooks2 &
                  (GDO_HOOK2_DDCPREDDCQUERY | GDO_HOOK2_DDCREADLINE | 
                   GDO_HOOK2_DDCWRITELINE | GDO_HOOK2_DDCPOSTDDCQUERY |
                   GDO_HOOK2_SETDSPLCONNECTOR)),
                   "Required DDCReadLine and/or DDCWriteLine hooks missing. "
                   "Ignoring new hooks.");

    return FALSE;
  }
} // bUseDalBasedDdc()

/******************************Public*Routine******************************\
* BOOL bIsDisplayDDCPhysicallyConnected(LPHW_DAL_EXTENSION lpHDE, 
*         LPDEVGDO lpDisplay)
*
* Make a DDC query. If the query succeeds and display type reported in
* the query coinsides with GDO's type then there is a connection. If DDC
* query fails then call GDO (it might know how to detect if it is connected 
* or not). First tries to query over DVI and then if this fails - over VGA
* connector.
*
\**************************************************************************/

BOOL
bIsDisplayDDCPhysicallyConnected(
  LPHW_DAL_EXTENSION  lpHDE,      // DAL instance
  LPDEVGDO            lpDisplay)  // Display structure
{
  DALDEBUG((DALDBG_ENTRY_EXIT, "bIsDisplayDDCPhysicallyConnected- Entry"));

    // Can use new style DDC implementation - must have all three following
    // hooks in place.
    //
  if (bUseDalBasedDdc(lpDisplay))
  {   // Only DAL knows how to accomplish DDC query

    EDID_BUFFER    EdidQueryBuffer;

      // This will cause bGetEdidData to try all connectors in turn till success
      //
    lpDisplay->ulFlags &= ~GDO_CONNECTOR_ESTABLISHED;

    // NOTE: REDSTONE and other test environment options are GDO's responsibility:
    // DO NOT HOOK IF CANNOT SUPPORT (Alright if test environment flags cannot be
    // changed dynamically - read from registry at enable time (once))

      // TBD: Make rather a quick query
    if(!bGetEdidData(lpHDE, lpDisplay, &EdidQueryBuffer))
    {   // Failed DDC query on all connectors

      DALDEBUG((DALDBG_NORMAL, "Could not detect connection through DDC, ask GDO as last resort"));
      DALDEBUG((DALDBG_ENTRY_EXIT, "bIsDisplayDDCPhysicallyConnected- Exit"));
      return lpDisplay->lpHWED->pfnIsDisplayPhysicallyConnected(lpDisplay->hGDO);
    }
       
    // Return TRUE if DDC-reported display type is expected
    //
    //if (lpDisplay->lpHWED->ulDisplayType 
    //    & ulEdidGetDisplayType(&EdidQueryBuffer))
    //  return TRUE;
    DALDEBUG((DALDBG_ENTRY_EXIT, "bIsDisplayDDCPhysicallyConnected- Exit"));
    return TRUE;
  }
  else
  {   // GDO implements DDC (obsolete), just call GDO
    DALDEBUG((DALDBG_ENTRY_EXIT, "bIsDisplayDDCPhysicallyConnected- Exit"));
    return lpDisplay->lpHWED->pfnIsDisplayPhysicallyConnected(lpDisplay->hGDO);
  }
} // bIsDisplayDDCPhysicallyConnected()

/******************************Public*Routine******************************\
* BOOL bGetEdidData(LPHW_DAL_EXTENSION lpHDE, LPDEVGDO lpDisplay,
*                   LPEDID_BUFFER lpEDIDBuf)
*
* This function will call the NO-BIOS code to get the EDID information.
*
\**************************************************************************/

BOOL 
bGetEdidData(
  LPHW_DAL_EXTENSION  lpHDE,      // DAL instance
  LPDEVGDO            lpDisplay,  // Display structure
  LPEDID_BUFFER       lpEDIDBuf)  // Uninitialized EDID buffer structure
{
  DALDEBUG((DALDBG_ENTRY_EXIT, "bGetEdidData- Entry"));

  DALASSERT(NULL != lpHDE, "lpHDE is NULL!");
  DALASSERT(NULL != lpDisplay, "lpDisplay is NULL!");

    // Can use new style DDC implementation - must have all three following
    // hooks in place.
    //
  if (bUseDalBasedDdc(lpDisplay))
  {
    BOOL bOK = FALSE;

    // Initialize EDID_BUFFER structure
    //
    lpEDIDBuf->ulSize = sizeof(lpEDIDBuf->aucEdidDataBuffer); // Maximum available size
    // BUGBUG: = EDID_DATA_SIZE; // Maximum required EDID size
    lpEDIDBuf->ulFormatId = 0;  // Assume unknown (invalid) format
    
    // Make a standard DDC query, try different connectors
    //
    if ((lpDisplay->lpHWED->ulFunctionHooks2 & GDO_HOOK2_SETDSPLCONNECTOR)
        && !(lpDisplay->ulFlags & GDO_CONNECTOR_ESTABLISHED))
    {   // Display has more than one connector. None of them has been 
        // tried (established) yet

      USHORT  usConnectorIndex;
      BOOL    bUntriedConnectors = TRUE;

      for(usConnectorIndex = 0;
          bUntriedConnectors;
          usConnectorIndex++)
      {
        bUntriedConnectors = (*lpDisplay->lpHWED->pfnSetDisplayConnector)(lpDisplay->hGDO, usConnectorIndex);

        if(TRUE == (bOK = DDCQuery(lpHDE, lpDisplay, lpEDIDBuf)))
        {
          DALDEBUG((DALDBG_NORMAL, "Connected on %d connector", usConnectorIndex));
          break;
        }
      }
    }
    else
    {
      bOK = DDCQuery(lpHDE, lpDisplay, lpEDIDBuf);
    }
    
    if (FALSE == bOK)
	{
	  DALDEBUG((DALDBG_ENTRY_EXIT, "bGetEdidData- Exit"));
      return FALSE;
	}

    lpDisplay->ulFlags |= GDO_CONNECTOR_ESTABLISHED;

    // Analyze and patch EDID data if necessary
    //
    if (FALSE == FilterEdidData(lpEDIDBuf))
	{
	  DALDEBUG((DALDBG_ENTRY_EXIT, "bGetEdidData- Exit"));
      return FALSE;
	}
	DALDEBUG((DALDBG_ENTRY_EXIT, "bGetEdidData- Exit"));
    return TRUE;
  }
  else
  {   // Old DDC-style GDO

    if (lpDisplay->lpHWED->ulFunctionHooks & GDO_HOOK_GET_EDID_DATA)
    {   // Obsolete hook is supported by GDO: use it rather than new
        // DDC implementation in DAL
      DALDEBUG((DALDBG_ENTRY_EXIT, "bGetEdidData- Exit"));
      return (*lpDisplay->lpHWED->pfnGetEdidData)(lpDisplay->hGDO, lpEDIDBuf);
    }
  }
  DALDEBUG((DALDBG_ENTRY_EXIT, "bGetEdidData- Exit"));
  return FALSE;
} // bGetEdidData()

/******************************Public*Routine******************************\
* ULONG GetStandardEdidLength(LPUCHAR lpucEdidDataBuf)
*
* Determine standard EDID data buffer length according to EDID version.
* Version 1 has 128 bytes and version 2 has 256 bytes. 8 first bytes of 
* EDID data must be available.
*
\**************************************************************************/

ULONG
GetStandardEdidLength(LPUCHAR lpucEdidDataBuf)
{
	if (0x00 == lpucEdidDataBuf[0]
		 && 0xff == lpucEdidDataBuf[1]
		 && 0xff == lpucEdidDataBuf[2]
		 && 0xff == lpucEdidDataBuf[3]
		 && 0xff == lpucEdidDataBuf[4]
		 && 0xff == lpucEdidDataBuf[5]
		 && 0xff == lpucEdidDataBuf[6]
		 && 0x00 == lpucEdidDataBuf[7])
		 return EDID_VER_1_STDLEN;
	else
	{
		if (0x20 == lpucEdidDataBuf[0])
			return EDID_VER_2_STDLEN;
	}

	return 0;		// Unknown format
}	// GetStandardEdidLength()

/******************************Public*Routine******************************\
* ULONG GetDisplayTypeFromEdid(LPEDID_BUFFER lpEDIDBuf)
*
* Return display type flag from EDID data. Full standard length of EDID
* data must be available.
*
\**************************************************************************/
ULONG
GetDisplayTypeFromEdid(LPEDID_BUFFER lpEDIDBuf)
{
  DALASSERT(lpEDIDBuf != NULL,
    "GetDisplayTypeFromEdid: lpEDIDBuf is invalid ");

  switch (lpEDIDBuf->ulFormatId & ~EDID_VER_REVMASK)
  {
  case EDID_VER_10 & ~EDID_VER_REVMASK:
    {   // Version 1: Byte 0x14, Bit 7, Analog = 0, Digital = 1
      
      if(lpEDIDBuf->ulSize < 0x14 + 1)
      {
        DALASSERT(FALSE, "EDID buffer too short");
        return HW_DISPLAY_UNKNOWN;
      }

      if (lpEDIDBuf->aucEdidDataBuffer[0x14] >> 7)
        return HW_DISPLAY_TYPES_DIGITAL_MASK;
      else
        return HW_DISPLAY_TYPES_CRT_MASK;
    }
    
  case EDID_VER_20 & ~EDID_VER_REVMASK:
    {   // Version 2: Byte 0x4F, Bits 7 - 4, CRT = 0, LCD = 1
      
      if(lpEDIDBuf->ulSize < 0x4F + 1)
      {
        DALASSERT(FALSE, "EDID buffer too short");
        return HW_DISPLAY_UNKNOWN;
      }

      if (lpEDIDBuf->aucEdidDataBuffer[0x4F] >> 4)
        return HW_DISPLAY_TYPES_DIGITAL_MASK;
      else
        return HW_DISPLAY_TYPES_CRT_MASK;
    }
    
  default :
    return HW_DISPLAY_UNKNOWN;
  }
} // GetDisplayTypeFromEdid

/******************************Private*Routine*****************************\
* BOOL FilterEdidData(LPEDID_BUFFER lpEDIDBuf)
*
* Fix misreported EDID data or do any change to it before it is reported 
* to DAL / Windows. Return FALSE to fail DDC query if necessary.
*
\**************************************************************************/

static BOOL 
FilterEdidData(
  LPEDID_BUFFER lpEDIDBuf)
{
  if (EDID_VER_1_STDLEN == lpEDIDBuf->ulSize)
  {   // Version 1

    // HP M50 monitor fix.  Some of the M50 monitors report and EDID version 2.1
    // when it really should be 1.2.
    //
    if (lpEDIDBuf->ulFormatId == 0x00000201)
    {
      // Check to see if this is an HP M50 monitor
      //
      if ((lpEDIDBuf->aucEdidDataBuffer[8]== DDC_HP_ID_BYTE1) &&
          (lpEDIDBuf->aucEdidDataBuffer[9]== DDC_HP_ID_BYTE2) &&
          (((lpEDIDBuf->aucEdidDataBuffer[10]== DDC_HP_M50_ID_BYTE1) &&
            (lpEDIDBuf->aucEdidDataBuffer[11]== DDC_HP_M50_ID_BYTE2)) ||
           ((lpEDIDBuf->aucEdidDataBuffer[10] == DDC_HP_M50_ID2_BYTE1) &&
            (lpEDIDBuf->aucEdidDataBuffer[11] == DDC_HP_M50_ID2_BYTE2))))
      {
        lpEDIDBuf->ulFormatId = EDID_VER_12;  // 0x102
      }
    }
  }

  return TRUE;
} // FilterEdidData()

/******************************Private*Routine*****************************\
* BOOL DDCQuery(LPHW_DAL_EXTENSION lpHDE, LPDEVGDO lpDisplay,
*               LPEDID_BUFFER lpEdidBuf)
*
* Make a DDC query.
*
\**************************************************************************/

static BOOL
DDCQuery(
  LPHW_DAL_EXTENSION  lpHDE,      // DAL instance
  LPDEVGDO            lpDisplay,  // Display structure
  LPEDID_BUFFER       lpEDIDBuf)  // EDID exchange buffer structure
{
  DALDDC_DDCCONTEXT ddcContext;
  BOOL              bRetCode;
  ULONG             ulMaxDDCTries;
  
  DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Entry"));
  DALASSERT(NULL != lpEDIDBuf, "lpEDIDBuf is NULL!");
  
  // Cannot do it here, must be done in GDO.
  // The proper way of doing this would be just not enabling the DCM hooks:
  // GDO_HOOK_GET_EDID_DATA
  // GDO_HOOK2_DDCPREDDCQUERY, GDO_HOOK2_DDCREADLINE, GDO_HOOK2_DDCWRITELINE
  //    if running on Redstone return FALSE. It hangs on NT
  //  if (lpR6Crt->ulTestEnvr == GCOGDO_TESTENVR_REDSTONE)
  //  {
  //    return FALSE;
  //  }
  
  ddcContext.lpHDE        = lpHDE;
  ddcContext.lpDisplay        = lpDisplay;
  ddcContext.lpucQueryBuffer  = lpEDIDBuf->aucEdidDataBuffer;
  ddcContext.ulLength     = lpEDIDBuf->ulSize;

  ulMaxDDCTries = 1;
  if (  (DALRULE2_DDC1SUPPORT & lpHDE->ulDalRule2)
      &&(HW_DISPLAY_TYPES_CRT_MASK & lpDisplay->lpHWED->ulDisplayType))
  // only support DDC1 for analog display devices.
  {
    ulMaxDDCTries = MAX_DDC1_TRIES;
  }
  
  // Call GDO to prepare the DDC line  
  if (lpDisplay->lpHWED->ulFunctionHooks2 
      & GDO_HOOK2_DDCPREDDCQUERY)
  {
    if (FALSE == lpDisplay->
        lpHWED->pfnDDC_I2C_PreDDCQuery(lpDisplay->hGDO))
	{
	   DALDEBUG((DALDBG_ENTRY_EXIT, "DDCQuery- Exit"));
       return FALSE;
	}
  }

  do
  {
    bRetCode = DDCQueryCallback(&ddcContext);
    // bRetCode = (BOOL) SYNCEXECUTION(lpHDE->hDDL, VpLowPriority, (PMINIPORT_SYNCHRONIZE_ROUTINE)DDCQueryCallback, &ddcContext);
    if (bRetCode)
    {
      break;
    }
    DDC_DELAY_MILLISECONDS(2);
  } while (ulMaxDDCTries--);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -