Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

708 lines
18 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
clddc2b.c
Abstract:
This module checks for a DDC monitor, and returns the
established Timings value from the EDID if found.
Environment:
Kernel mode only
Notes:
Revision History:
// plc3 10-23-95 VESA DDC2B support.
--*/
//---------------------------------------------------------------------------
#include "dderror.h"
#include "devioctl.h"
#include "miniport.h"
#include "ntddvdeo.h"
#include "video.h"
#include "cirrus.h"
#define ERROR 0
#define OFF 0
#define ON 1
#define SDA_BIT 2
#define SCL_BIT 1
#define SCL_BIT_ON 1
#define SCL_BIT_OFF 0
#define DELAY_COUNT 255
UCHAR WaitCount ;
UCHAR Error ;
VOID ReadVESATiming(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID EnableDDC(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN IsDDC2(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID DisableDDC(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID StartDDC(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID StopDDC(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID ProcessDDC2(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN ReadSDA(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN ReadSCL(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN ReadBit(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN ReadByte(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID SetSCL(
PHW_DEVICE_EXTENSION HwDeviceExtension,
UCHAR status
);
VOID SetData(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN SetClock(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID WaitVerticalRetrace(
PHW_DEVICE_EXTENSION HwDeviceExtension,
UCHAR count
);
VOID WaitDelay(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID ClearData(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN SendByte(
PHW_DEVICE_EXTENSION HwDeviceExtension,
UCHAR data
);
BOOLEAN SendDDCCommand(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
#if defined(ALLOC_PRAGMA)
#pragma alloc_text (PAGE,ReadVESATiming)
#pragma alloc_text (PAGE,EnableDDC)
#pragma alloc_text (PAGE,IsDDC2)
#pragma alloc_text (PAGE,DisableDDC)
#pragma alloc_text (PAGE,StartDDC)
#pragma alloc_text (PAGE,StopDDC)
#pragma alloc_text (PAGE,ProcessDDC2)
#pragma alloc_text (PAGE,ReadSDA)
#pragma alloc_text (PAGE,ReadSCL)
#pragma alloc_text (PAGE,ReadBit)
#pragma alloc_text (PAGE,ReadByte)
#pragma alloc_text (PAGE,SetSCL)
#pragma alloc_text (PAGE,SetData)
#pragma alloc_text (PAGE,SetClock)
#pragma alloc_text (PAGE,WaitVerticalRetrace)
#pragma alloc_text (PAGE,WaitDelay)
#pragma alloc_text (PAGE,ClearData)
#pragma alloc_text (PAGE,SendByte)
#pragma alloc_text (PAGE,SendDDCCommand)
#endif
UCHAR EDIDBuffer[128] ;
UCHAR EDIDTiming_I ;
UCHAR EDIDTiming_II ;
UCHAR EDIDTiming_III ;
UCHAR DDC2BFlag ;
UCHAR SDAValue ;
/*-------------------------------------------------------------------------*/
VOID EnableDDC (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ReadSR08 ;
UCHAR WaitCount = 2 ;
VideoDebugPrint((0, "CLDDC2B!EnableDDC\n"));
VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
0x08) ;
ReadSR08 = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) ;
// Enable DDC2B Configuration
ReadSR08 |= 0x43 ;
VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
ReadSR08) ;
WaitVerticalRetrace (HwDeviceExtension, WaitCount) ;
} /*----- EnableDDC -----*/
/*-------------------------------------------------------------------------*/
VOID DisableDDC (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ReadSEQADDR, ReadSEQDATA ;
UCHAR DDCStatus ;
VideoDebugPrint((0, "CLDDC2B!DisableDDC\n"));
if ((DDCStatus = SendDDCCommand ( HwDeviceExtension )) == 1)
goto DDC_ERROR ;
// i 3c5 ReadSEQDATA
ReadSEQDATA = VideoPortReadPortUchar ( HwDeviceExtension->IOAddress +
SEQ_DATA_PORT ) ;
// Disable DDC2B Configuration
ReadSEQDATA &= 0xBC ;
// o 3c5 ReadSEQDATA
VideoPortWritePortUchar ( HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
ReadSEQDATA ) ;
DDC_ERROR:
return ;
} /*------- DisableDDC -------*/
/*-------------------------------------------------------------------------*/
VOID ProcessDDC2 (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR DDCStatus, i ;
UCHAR checksum, header ;
VideoDebugPrint((0, "CLDDC2B!ProcessDDC2\n"));
DDC2BFlag = 0 ;
if ((DDCStatus = SendDDCCommand ( HwDeviceExtension )) == 1) {
VideoDebugPrint((0, "CLDDC2B!ProcessDDC2: Infinite wait state ...\n"));
goto PROCESSDDC_EXIT ;
}
for (i = 0; i < 128; i++) {
EDIDBuffer[i] = ReadByte (HwDeviceExtension) ;
if (Error) {
VideoDebugPrint((0, "CLDDC2B!ProcessDDC2: Infinite wait state ...\n"));
goto PROCESSDDC_EXIT ;
}
}
//
// Check EDID table 8-byte header
// The correct first 8 bytes of EDID table is 0x00, 0xFF, 0xFF, 0xFF,
// 0xFF, 0xFF, 0xFF, 0x00
//
if ((EDIDBuffer[0] != 0) ||
(EDIDBuffer[7] != 0)) {
VideoDebugPrint((0, "CLDDC2B: Invalid EDID header table\n"));
StopDDC (HwDeviceExtension) ;
return ;
}
for (i = 1; i < 7; i++) {
if (EDIDBuffer[i] != 0xFF) {
VideoDebugPrint((0, "CLDDC2B: Invalid EDID header table\n"));
StopDDC (HwDeviceExtension) ;
return ;
}
}
//
// Calculate checksum of 128-byte EDID table.
//
checksum = 0x00 ;
for (i = 0; i < 128; i++) {
checksum += EDIDBuffer[i] ;
}
VideoDebugPrint((0, "CLDDC2B: EDID Table check sum = %d\n", checksum));
//
// EDID table checksum must be zero.
//
if (checksum) {
VideoDebugPrint((0, "CLDDC2B: Invalid checksum of EDID table\n"));
}
else
{
//
// Set DDC2B Flag and find timing values.
//
DDC2BFlag = 1 ;
EDIDTiming_I = EDIDBuffer[35] ;
EDIDTiming_II = EDIDBuffer[36] ;
EDIDTiming_III = EDIDBuffer[37] ;
VideoDebugPrint((0, "CLDDC2B: DDC2B is supported\n"));
}
PROCESSDDC_EXIT:
StopDDC (HwDeviceExtension) ;
return ;
} /*------- ProcessDDC2 -------*/
/*-------------------------------------------------------------------------*/
VOID StartDDC (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
VideoDebugPrint((0, "DDC2B!StartDDC\n"));
SetSCL (HwDeviceExtension, ON) ;
ClearData (HwDeviceExtension) ;
SetSCL (HwDeviceExtension, OFF) ;
} /*------- StartDDC -------*/
/*-------------------------------------------------------------------------*/
VOID StopDDC (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
VideoDebugPrint((0, "DDC2B!StopDDC\n"));
SetSCL (HwDeviceExtension, ON) ;
SetData (HwDeviceExtension) ;
} /*------- StopDDC -------*/
/*-------------------------------------------------------------------------*/
BOOLEAN ReadSCL (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ReadSEQDATA, status ;
// i 3c5 ReadSEQDATA
ReadSEQDATA = VideoPortReadPortUchar ( HwDeviceExtension->IOAddress +
SEQ_DATA_PORT ) ;
// Read SR08.B2
ReadSEQDATA = ( (ReadSEQDATA) & 0x04 ) >> 2 ;
return (ReadSEQDATA) ;
} /*------- ReadSCL -------*/
/*-------------------------------------------------------------------------*/
VOID SetSCL(
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension,
UCHAR status
)
{
UCHAR ReadSEQADDR, ReadSEQDATA ;
// i 3c5 ReadSEQDATA
ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) ;
ReadSEQDATA = ( ( ReadSEQDATA & 0xFE ) | status ) ;
// o 3c5 ReadSEQDATA
VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
ReadSEQDATA) ;
WaitDelay (HwDeviceExtension) ;
} /*------- SetSCL -------*/
/*-------------------------------------------------------------------------*/
BOOLEAN ReadSDA (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ReadSEQADDR, ReadSEQDATA ;
// i 3c5 ReadSEQDATA
ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) ;
ReadSEQDATA = ( ReadSEQDATA & 0x80 ) >> 7 ;
return ( ReadSEQDATA ) ;
} /*------- ReadSDA -------*/
/*-------------------------------------------------------------------------*/
VOID ClearData
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ReadSEQADDR, ReadSEQDATA ;
// i 3c5 ReadSEQDATA
ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) ;
ReadSEQDATA &= 0xFD ;
// o 3c5 ReadSEQDATA
VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
ReadSEQDATA) ;
WaitDelay (HwDeviceExtension) ;
} /*------- ClearData -------*/
/*-------------------------------------------------------------------------*/
VOID SetData
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ReadSEQADDR, ReadSEQDATA ;
// i 3c5 ReadSEQDATA
ReadSEQDATA = VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) ;
ReadSEQDATA |= 0x02 ;
// o 3c5 ReadSEQDATA
VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
ReadSEQDATA) ;
WaitDelay (HwDeviceExtension) ;
} /*------- SetData -------*/
/*-------------------------------------------------------------------------*/
BOOLEAN SetClock
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
ULONG i ;
UCHAR status ;
SetSCL (HwDeviceExtension, ON) ;
for (i = 0; i < DELAY_COUNT; i++)
status = ReadSCL (HwDeviceExtension) ;
SetSCL (HwDeviceExtension, OFF) ;
if (!status)
VideoDebugPrint((0, "DDC2B!SetClock: Infinite wait state ...\n"));
if (status == 1)
return ( FALSE ) ; // retuern 0 -> OK
else
return ( TRUE ) ; // retuern 1 -> Infinite wait state
} /*------- SetClock -------*/
/*-------------------------------------------------------------------------*/
BOOLEAN ReadBit
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
USHORT i ;
UCHAR bit ;
SetSCL (HwDeviceExtension, ON) ;
for (i = 0; i < DELAY_COUNT; i++)
ReadSCL (HwDeviceExtension) ;
bit = ReadSDA (HwDeviceExtension) ;
SetSCL (HwDeviceExtension, OFF) ;
return ( bit ) ;
} /*------- ReadBit -------*/
/*-------------------------------------------------------------------------*/
BOOLEAN ReadByte
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ReadByteValue, bit, i ;
SetData ( HwDeviceExtension ) ;
ReadByteValue = 0 ;
for (i = 0; i < 8; i++) {
ReadByteValue <<= 1 ;
bit = ReadBit ( HwDeviceExtension ) ;
ReadByteValue |= bit ;
}
if ((bit & 0x02) != 0) {
SetData ( HwDeviceExtension ) ;
} else {
ClearData ( HwDeviceExtension ) ;
}
SetClock ( HwDeviceExtension ) ;
SetData ( HwDeviceExtension ) ;
return (ReadByteValue) ;
} /*----- ReadByte -----*/
/*-------------------------------------------------------------------------*/
BOOLEAN SendByte (
/*-------------------------------------------------------------------------*/
PHW_DEVICE_EXTENSION HwDeviceExtension,
UCHAR data
)
{
UCHAR i ;
UCHAR Mask[8] = { 0x80, 0x40, 0x20, 0x10,
0x08, 0x04, 0x02, 0x01 } ;
for (i = 0; i < 8; i++)
{
if (data & Mask[i]) {
SetData ( HwDeviceExtension ) ;
} else {
ClearData ( HwDeviceExtension ) ;
}
Error = SetClock ( HwDeviceExtension ) ;
}
if (Error) {
SetSCL ( HwDeviceExtension, OFF ) ;
ClearData (HwDeviceExtension) ;
} else {
SetData ( HwDeviceExtension ) ;
SetSCL ( HwDeviceExtension, ON ) ;
ReadBit ( HwDeviceExtension ) ; // Discard acknowledge bit
}
return (Error) ;
} /*------- SendByte -------*/
/*-------------------------------------------------------------------------*/
BOOLEAN IsDDC2
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR DDCStatus, SCLStatus ;
VideoDebugPrint((0, "DDC2B!IsDDC2\n"));
SetSCL (HwDeviceExtension, OFF) ;
SCLStatus = ReadSCL(HwDeviceExtension) ;
if (SCLStatus != 0) {
return ( FALSE ) ;
}
SetSCL (HwDeviceExtension, ON) ;
SCLStatus = ReadSCL (HwDeviceExtension) ;
if (SCLStatus != 1) {
return ( FALSE ) ;
}
return ( TRUE ) ;
} /*------- IsDDC2 -------*/
/*-------------------------------------------------------------------------*/
BOOLEAN SendDDCCommand
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR ClockStatus ;
VideoDebugPrint((0, "DDC2B!SendDDCCommand\n"));
StartDDC ( HwDeviceExtension ) ;
ClockStatus = SendByte ( HwDeviceExtension, 0xA0 ) ;
if (ClockStatus)
VideoDebugPrint((0, "DDC2B!SendDDCCommand: Infinite wait state ...\n"));
ClockStatus = SendByte ( HwDeviceExtension, 0x00 ) ;
if (ClockStatus)
VideoDebugPrint((0, "DDC2B!SendDDCCommand: Infinite wait state ...\n"));
StopDDC ( HwDeviceExtension ) ;
StartDDC ( HwDeviceExtension ) ;
ClockStatus = SendByte ( HwDeviceExtension, 0xA1 ) ;
if (ClockStatus)
VideoDebugPrint((0, "DDC2B!SendDDCCommand: Infinite wait state ...\n"));
SetData ( HwDeviceExtension ) ;
return (ClockStatus) ;
} /*------- SendDDCCommand -------*/
/*-------------------------------------------------------------------------*/
VOID WaitDelay
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
PUCHAR InStatPort ;
//
// Set up port addresses for color/mono
//
if (VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
MISC_OUTPUT_REG_READ_PORT) & 0x01) {
InStatPort = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR ;
} else {
InStatPort = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO ;
}
while ((VideoPortReadPortUchar (InStatPort) & 0x01) != 0) ;
while ((VideoPortReadPortUchar (InStatPort) & 0x01) == 0) ;
while ((VideoPortReadPortUchar (InStatPort) & 0x01) != 0) ;
} /*------- wait_delay -------*/
/*-------------------------------------------------------------------------*/
VOID WaitVerticalRetrace
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension,
UCHAR waitcount
)
{
PUCHAR InStatPort ;
ULONG i ;
//
// Set up port addresses for color/mono
//
if (VideoPortReadPortUchar (HwDeviceExtension->IOAddress +
MISC_OUTPUT_REG_READ_PORT) & 0x01) {
InStatPort = INPUT_STATUS_1_COLOR + HwDeviceExtension->IOAddress;
} else {
InStatPort = INPUT_STATUS_1_MONO + HwDeviceExtension->IOAddress;
}
for (i = 0; i < waitcount; i++)
{
while ((VideoPortReadPortUchar (InStatPort) & 0x08) != 0) ;
while ((VideoPortReadPortUchar (InStatPort) & 0x08) == 0) ;
}
} /*------- WaitVerticalRetrace -------*/
/*-------------------------------------------------------------------------*/
VOID ReadVESATiming
/*-------------------------------------------------------------------------*/
(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
UCHAR status ;
VideoDebugPrint((0, "DDC2B!ReadVESATiming\n"));
EnableDDC (HwDeviceExtension) ;
if ((status = IsDDC2 (HwDeviceExtension)) != 0x00) {
ProcessDDC2 (HwDeviceExtension) ;
}
DisableDDC (HwDeviceExtension) ;
return ;
} /*----- ReadVESATiming -----*/