mirror of https://github.com/lianthony/NT4.0
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.
1583 lines
54 KiB
1583 lines
54 KiB
/**************************************************************************\
|
|
|
|
$Header: o:\src/RCS/DDC.C 1.2 95/07/07 06:14:54 jyharbec Exp $
|
|
|
|
$Log: DDC.C $
|
|
* Revision 1.2 95/07/07 06:14:54 jyharbec
|
|
* *** empty log message ***
|
|
*
|
|
* Revision 1.1 95/05/02 05:16:10 jyharbec
|
|
* Initial revision
|
|
*
|
|
|
|
\**************************************************************************/
|
|
|
|
/*/****************************************************************************
|
|
* name: DDC.C
|
|
*
|
|
* description:
|
|
*
|
|
* designed: Benoit Leblanc
|
|
* last modified: $Author: jyharbec $, $Date: 95/07/07 06:14:54 $
|
|
*
|
|
* version: $Id: DDC.C 1.2 95/07/07 06:14:54 jyharbec Exp $
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifndef WINDOWS_NT
|
|
#include <dos.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#endif
|
|
|
|
#include "switches.h"
|
|
#include "defbind.h"
|
|
#include "bind.h"
|
|
#include "mga.h"
|
|
#include "mgai.h"
|
|
#include "edid.h"
|
|
|
|
#ifdef WIN31
|
|
#include "windows.h"
|
|
#endif
|
|
|
|
#ifdef WINDOWS_NT
|
|
#include "ntmga.h"
|
|
#endif
|
|
|
|
#define DEBUG 0
|
|
#define DEVICE_ID 0xA0
|
|
#define STRT_ADDR 0x00
|
|
|
|
#ifndef DONT_USE_DDC
|
|
|
|
/* variables */
|
|
|
|
byte CheckDDCDone = FALSE;
|
|
byte FindDDC[NB_BOARD_MAX] = {0};
|
|
enum CRTCaction {BACKUP,RESTORE};
|
|
byte SupportDDC[NB_BOARD_MAX] = {0};
|
|
dword DelayTime;
|
|
EDID DataEdid;
|
|
word EdidBuffer[128];
|
|
byte CRTCValReg[32];
|
|
bool UsingDDC;
|
|
|
|
VesaSet VesaParam[20] = {
|
|
/*00*/{ 640, 480, 75, 0, 31500, 640, 16, 64, 120, 0, 480, 1, 3, 16, 0, 0, 0, 0, 0 ,
|
|
31500, 640, 16, 64, 120, 0, 480, 1, 3, 16, 0, 0, 0, 0, 0 ,
|
|
31500, 640, 16, 64, 120, 0, 480, 1, 3, 16, 0, 0, 0, 0, 0},
|
|
/*01*/{ 640, 480, 72, 0, 31500, 640, 24, 40, 128, 0, 480, 9, 3, 28, 0, 0, 0, 0, 0 ,
|
|
31500, 640, 24, 40, 128, 0, 480, 9, 3, 28, 0, 0, 0, 0, 0 ,
|
|
31500, 640, 24, 40, 128, 0, 480, 9, 3, 28, 0, 0, 0, 0, 0},
|
|
/*02*/{ 640, 480, 60, 0, 25175, 640, 16, 96, 48, 0, 480, 10, 2, 33, 0, 0, 0, 0, 0 ,
|
|
25175, 640, 16, 96, 48, 0, 480, 10, 2, 32, 0, 0, 0, 0, 0 ,
|
|
25175, 640, 16, 96, 48, 0, 480, 10, 2, 32, 0, 0, 0, 0, 0},
|
|
/*03*/{ 800, 600, 75, 0, 49500, 800, 16, 80, 160, 0, 600, 1, 3, 21, 0, 0, 0, 1, 1 ,
|
|
49500, 800, 16, 80, 160, 0, 600, 1, 3, 21, 0, 0, 0, 1, 1 ,
|
|
49500, 800, 16, 80, 160, 0, 600, 1, 3, 21, 0, 0, 0, 1, 1},
|
|
/*04*/{ 800, 600, 72, 0, 50000, 800, 56, 120, 64, 0, 600, 37, 6, 23, 0, 0, 0, 1, 1 ,
|
|
50000, 800, 56, 120, 64, 0, 600, 37, 6, 23, 0, 0, 0, 1, 1 ,
|
|
50000, 800, 56, 120, 64, 0, 600, 37, 6, 23, 0, 0, 0, 1, 1},
|
|
/*05*/{ 800, 600, 60, 0, 40000, 800, 40, 128, 88, 0, 600, 1, 4, 23, 0, 0, 0, 1, 1 ,
|
|
40000, 800, 40, 128, 88, 0, 600, 1, 4, 23, 0, 0, 0, 1, 1 ,
|
|
40000, 800, 40, 128, 88, 0, 600, 1, 4, 23, 0, 0, 0, 1, 1},
|
|
/*06*/{ 800, 600, 56, 0, 36000, 800, 24, 72, 128, 0, 600, 1, 2, 22, 0, 0, 0, 1, 1 ,
|
|
36000, 800, 24, 72, 128, 0, 600, 1, 2, 22, 0, 0, 0, 1, 1 ,
|
|
36000, 800, 24, 72, 128, 0, 600, 1, 2, 22, 0, 0, 0, 1, 1},
|
|
/*07*/{ 1024, 768, 75, 0, 78750, 1024, 16, 96, 176, 0, 768, 1, 3, 28, 0, 0, 0, 1, 1 ,
|
|
78750, 1024, 16, 96, 176, 0, 768, 1, 3, 28, 0, 0, 0, 1, 1 ,
|
|
78750, 1024, 16, 96, 176, 0, 768, 1, 3, 28, 0, 0, 0, 1, 1},
|
|
/*08*/{ 1024, 768, 70, 0, 75000, 1024, 24, 136, 144, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
|
|
75000, 1024, 24, 136, 144, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
|
|
75000, 1024, 24, 136, 144, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0},
|
|
/*09*/{ 1024, 768, 60, 0, 65000, 1024, 24, 136, 160, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
|
|
65000, 1024, 24, 136, 160, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0 ,
|
|
65000, 1024, 24, 136, 160, 0, 768, 3, 6, 29, 0, 0, 0, 0, 0},
|
|
/*10*/{ 1024, 768, 43, 0, 44900, 1024, 8, 176, 56, 0, 384, 0, 4, 20, 0, 0, 1, 1, 1 ,
|
|
44900, 1024, 8, 176, 56, 0, 384, 0, 4, 20, 0, 0, 1, 1, 1 ,
|
|
44900, 1024, 8, 176, 56, 0, 384, 0, 4, 20, 0, 0, 1, 1, 1},
|
|
/*11*/{ 1280, 1024, 75, 0, 135000, 1280, 16, 144, 248, 0, 1024, 1, 3, 38, 0, 0, 0, 1, 1 ,
|
|
135000, 1280, 16, 144, 248, 0, 1024, 1, 3, 38, 0, 0, 0, 1, 1 ,
|
|
135000, 1280, 16, 144, 248, 0, 1024, 1, 3, 38, 0, 0, 0, 1, 1},
|
|
/*12*/{ 1152, 882, 70, 0, 94500, 1152, 32, 96, 160, 0, 882, 1, 3, 52, 0, 0, 0, 1, 1 ,
|
|
94500, 1152, 32, 96, 160, 0, 882, 1, 3, 52, 0, 0, 0, 1, 1 ,
|
|
94500, 1152, 32, 96, 160, 0, 882, 1, 3, 52, 0, 0, 0, 1, 1},
|
|
/*13*/{ 1152, 882, 75, 0, 108000, 1152, 64, 128, 192, 0, 882, 1, 3, 52, 0, 0, 0, 1, 1 ,
|
|
108000, 1152, 64, 128, 192, 0, 882, 1, 3, 52, 0, 0, 0, 1, 1 ,
|
|
108000, 1152, 64, 128, 192, 0, 882, 1, 3, 52, 0, 0, 0, 1, 1},
|
|
/*14*/{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
/*15*/{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
/*16*/{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
/*17*/{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
{(word)-1}
|
|
};
|
|
|
|
VBoardVesaSet VBoardVesaParam;
|
|
|
|
/* Functions prototypes */
|
|
|
|
void CheckDDC(HwData * HwDataPtr);
|
|
byte ReadEdid(byte iBoard);
|
|
byte InDDCTable(dword DispWidth);
|
|
byte ExtractEdid(word *buffer);
|
|
byte FindHeader(byte *buffer);
|
|
void Boost_Vsync(void);
|
|
void EditCRTCReg(enum CRTCaction action);
|
|
|
|
#ifdef WINDOWS_NT
|
|
extern PMGA_DEVICE_EXTENSION pMgaDevExt;
|
|
extern void ScreenOn(void);
|
|
extern void ScreenOff(void);
|
|
extern HwData *pMgaBoardData;
|
|
|
|
Vidset *FindDDCFreq(dword DispWidth);
|
|
void Add1152Timings(void);
|
|
ULONG SetCounter(volatile byte _FAR *pBoardRegs);
|
|
VOID SetScl(volatile byte _FAR *pBoardRegs);
|
|
VOID SetSda(volatile byte _FAR *pBoardRegs);
|
|
VOID ClrScl(volatile byte _FAR *pBoardRegs);
|
|
VOID ClrSda(volatile byte _FAR *pBoardRegs);
|
|
UCHAR ReadSda(volatile byte _FAR *pBoardRegs);
|
|
UCHAR ReadScl(volatile byte _FAR *pBoardRegs);
|
|
VOID Delay(volatile byte _FAR *pBoardRegs, ULONG ulCounter);
|
|
VOID PullDwClock(volatile byte _FAR *pBoardRegs, ULONG ulCounter);
|
|
UCHAR SendStart(volatile byte _FAR *pBoardRegs, ULONG ulCounter);
|
|
VOID SendStop(volatile byte _FAR *pBoardRegs, ULONG ulCounter);
|
|
UCHAR WaitAck(volatile byte _FAR *pBoardRegs, ULONG ulCounter);
|
|
VOID SendAck(volatile byte _FAR *pBoardRegs, ULONG ulCounter);
|
|
VOID WriteByte(volatile byte _FAR *pBoardRegs, ULONG ulCounter, UCHAR ucData);
|
|
UCHAR ReadByte(volatile byte _FAR *pBoardRegs, ULONG ulCounter);
|
|
BOOLEAN DetectSDA(volatile byte _FAR *pBoardRegs);
|
|
VOID ScanSDA(volatile byte _FAR *pBoardRegs, word *Buffer, word *Dummy);
|
|
|
|
#if defined(ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE,CheckDDC)
|
|
#pragma alloc_text(PAGE,ReadEdid)
|
|
#pragma alloc_text(PAGE,InDDCTable)
|
|
#pragma alloc_text(PAGE,FindDDCFreq)
|
|
#pragma alloc_text(PAGE,Add1152Timings)
|
|
#pragma alloc_text(PAGE,ExtractEdid)
|
|
#pragma alloc_text(PAGE,FindHeader)
|
|
#pragma alloc_text(PAGE,Boost_Vsync)
|
|
#pragma alloc_text(PAGE,EditCRTCReg)
|
|
#pragma alloc_text(PAGE,SetCounter)
|
|
#pragma alloc_text(PAGE,SetScl)
|
|
#pragma alloc_text(PAGE,SetSda)
|
|
#pragma alloc_text(PAGE,ClrScl)
|
|
#pragma alloc_text(PAGE,ClrSda)
|
|
#pragma alloc_text(PAGE,ReadSda)
|
|
#pragma alloc_text(PAGE,ReadScl)
|
|
#pragma alloc_text(PAGE,Delay)
|
|
#pragma alloc_text(PAGE,PullDwClock)
|
|
#pragma alloc_text(PAGE,SendStart)
|
|
#pragma alloc_text(PAGE,SendStop)
|
|
#pragma alloc_text(PAGE,WaitAck)
|
|
#pragma alloc_text(PAGE,SendAck)
|
|
#pragma alloc_text(PAGE,WriteByte)
|
|
#pragma alloc_text(PAGE,ReadByte)
|
|
#pragma alloc_text(PAGE,DetectSDA)
|
|
#pragma alloc_text(PAGE,ScanSDA)
|
|
#endif
|
|
#endif /* #ifdef WINDOWS_NT */
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name: CheckDDC
|
|
*
|
|
* Description: This function initialise a table of video
|
|
* parameters with values returned by the EDID
|
|
* informations.
|
|
*
|
|
* return: NONE
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
void CheckDDC(HwData *HwDataPtr)
|
|
{
|
|
word i,j;
|
|
byte nb_board;
|
|
HwModeData *HwModeDataPtr;
|
|
|
|
|
|
/**** TVP3030 does not support GENERAL IO PINS *******/
|
|
/* No DDC support with this RAMDAC */
|
|
if ( (HwDataPtr[iBoard].EpromData.RamdacType>>8) == TVP3030)
|
|
return;
|
|
|
|
/* Calculate the number of board in the system */
|
|
for (nb_board = 0; HwDataPtr[nb_board].MapAddress != (dword) -1;)
|
|
nb_board++;
|
|
|
|
#ifdef WINDOWS_NT
|
|
// WARNING! Modify MGA_DEVICE_EXTENSION if the allocated size changes!
|
|
// Use memory allocated in the device extension.
|
|
VBoardVesaParam = (VBoardVesaSet)(&pMgaDevExt->VesaSet);
|
|
pMgaBoardData = HwDataPtr;
|
|
#else
|
|
if (!CheckDDCDone)
|
|
if ((VBoardVesaParam = (VBoardVesaSet)malloc(20 * nb_board * sizeof(VesaSet))) == 0)
|
|
return;
|
|
#endif
|
|
|
|
/* For each board we set a default mode */
|
|
for (i = 0; i < nb_board; i++)
|
|
{
|
|
/* initialise the buffer and reset the flags */
|
|
for (j = 0; j < 128; j++)
|
|
EdidBuffer[j] = 0;
|
|
|
|
if (mtxSelectHw(((HwData *)(HwDataPtr + i))) == mtxFAIL)
|
|
continue;
|
|
|
|
if ((HwModeDataPtr = mtxGetHwModes()) == mtxFAIL)
|
|
continue;
|
|
|
|
if (!CheckDDCDone)
|
|
memcpy(VBoardVesaParam + iBoard,VesaParam,20 * sizeof(VesaSet));
|
|
|
|
/* we verify if there is some DDC capabilities and then read it */
|
|
if (!CheckDDCDone)
|
|
FindDDC[iBoard] = ReadEdid(iBoard);
|
|
|
|
|
|
if (FindDDC[iBoard])
|
|
{
|
|
/* represent DDC available */
|
|
((HwData *)(HwDataPtr + i))->Features |= 0x01;
|
|
}
|
|
|
|
|
|
UsingDDC = FALSE;
|
|
|
|
/* if we find the Edid structure we must change the HwModes */
|
|
/* to reflect the DDC information if there is no mga.inf */
|
|
if ((mgainf == DefaultVidset) && FindDDC[iBoard])
|
|
{
|
|
UsingDDC = TRUE;
|
|
|
|
for (;HwModeDataPtr->DispWidth != (word)-1; HwModeDataPtr++)
|
|
if (!InDDCTable(HwModeDataPtr->DispWidth) || (HwModeDataPtr->DispType & 0x02))
|
|
HwModeDataPtr->DispType |= DISP_SUPPORT_NA; /* monitor limited */
|
|
}
|
|
|
|
}
|
|
|
|
CheckDDCDone = TRUE;
|
|
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : ReadEdid
|
|
*
|
|
* description : This function retrieve the EDID information
|
|
* block by using the DDC2B or the DDC1 protocol.
|
|
*
|
|
* Return :
|
|
* TRUE if we have correctly retrieve the Edid block
|
|
* FALSE if we have failed to correctly retrieve the Edid
|
|
* block
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
byte ReadEdid(byte iBoard)
|
|
{
|
|
byte find,retries;
|
|
word i;
|
|
#ifdef OS2
|
|
word * pTmp = EdidBuffer;
|
|
#endif
|
|
|
|
#if (defined(WIN31) || defined(OS2))
|
|
//#ifdef WIN31
|
|
|
|
DelayTime = (SetCounter(SELECTOROF(pMGA)) >> 8);
|
|
PullDwClock (SELECTOROF(pMGA),DelayTime);
|
|
|
|
find = 0;
|
|
retries = 0;
|
|
while (retries < 16)
|
|
{
|
|
if (SendStart (SELECTOROF(pMGA),DelayTime) != 0)
|
|
{
|
|
WriteByte (SELECTOROF(pMGA),DelayTime,DEVICE_ID);
|
|
|
|
if (WaitAck (SELECTOROF(pMGA),DelayTime) != 0)
|
|
{
|
|
WriteByte (SELECTOROF(pMGA),DelayTime,STRT_ADDR);
|
|
|
|
if (WaitAck (SELECTOROF(pMGA),DelayTime) != 0)
|
|
{
|
|
if (SendStart (SELECTOROF(pMGA),DelayTime) != 0)
|
|
{
|
|
WriteByte (SELECTOROF(pMGA),DelayTime,(DEVICE_ID | 1));
|
|
|
|
if (WaitAck (SELECTOROF(pMGA),DelayTime) != 0)
|
|
{
|
|
for (i = 0; i < 127; i++)
|
|
{
|
|
((byte *)&DataEdid)[i] = ReadByte (SELECTOROF(pMGA),DelayTime);
|
|
SendAck (SELECTOROF(pMGA),DelayTime);
|
|
}
|
|
((byte *)&DataEdid)[i] = ReadByte (SELECTOROF(pMGA),DelayTime);
|
|
SendStop (SELECTOROF(pMGA),DelayTime);
|
|
|
|
find = FindHeader((byte *)&DataEdid);
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
SendStop (SELECTOROF(pMGA),DelayTime);
|
|
}
|
|
retries++;
|
|
}
|
|
|
|
|
|
if (!find)
|
|
{
|
|
if (DetectSDA(SELECTOROF(pMGA)))
|
|
{
|
|
EditCRTCReg(BACKUP);
|
|
ScreenOff();
|
|
Boost_Vsync();
|
|
|
|
#ifdef OS2
|
|
ScanSDA(SELECTOROF(pMGA),SELECTOROF(pTmp),(dword)OFFSETOF(pTmp));
|
|
#else// NOT OS2
|
|
ScanSDA(SELECTOROF(pMGA),SELECTOROF(EdidBuffer),(dword)OFFSETOF(EdidBuffer));
|
|
#endif
|
|
|
|
find = ExtractEdid(EdidBuffer);
|
|
EditCRTCReg(RESTORE);
|
|
ScreenOn();
|
|
}
|
|
}
|
|
|
|
#else /* #ifdef WIN31 */
|
|
|
|
#ifdef WINDOWS_NT
|
|
|
|
DelayTime = (SetCounter(pMGA) >> 8);
|
|
PullDwClock(pMGA, DelayTime);
|
|
|
|
find = 0;
|
|
retries = 0;
|
|
while (retries < 16)
|
|
{
|
|
if (SendStart(pMGA, DelayTime) != 0)
|
|
{
|
|
WriteByte(pMGA, DelayTime, DEVICE_ID);
|
|
|
|
if (WaitAck(pMGA, DelayTime) != 0)
|
|
{
|
|
WriteByte(pMGA, DelayTime, STRT_ADDR);
|
|
|
|
if (WaitAck(pMGA, DelayTime) != 0)
|
|
{
|
|
if (SendStart(pMGA, DelayTime) != 0)
|
|
{
|
|
WriteByte(pMGA, DelayTime, (DEVICE_ID | 1));
|
|
|
|
if (WaitAck(pMGA, DelayTime) != 0)
|
|
{
|
|
for (i = 0; i < 127; i++)
|
|
{
|
|
((byte *)&DataEdid)[i] = ReadByte(pMGA, DelayTime);
|
|
SendAck(pMGA, DelayTime);
|
|
}
|
|
((byte *)&DataEdid)[i] = ReadByte(pMGA, DelayTime);
|
|
|
|
find = FindHeader((byte *)&DataEdid);
|
|
SendStop(pMGA, DelayTime);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SendStop(pMGA, DelayTime);
|
|
}
|
|
retries++;
|
|
}
|
|
|
|
|
|
if (!find)
|
|
{
|
|
if (DetectSDA(pMGA))
|
|
{
|
|
EditCRTCReg(BACKUP);
|
|
ScreenOff();
|
|
Boost_Vsync();
|
|
|
|
ScanSDA(pMGA, EdidBuffer, 0);
|
|
|
|
find = ExtractEdid(EdidBuffer);
|
|
EditCRTCReg(RESTORE);
|
|
ScreenOn();
|
|
}
|
|
}
|
|
|
|
#else /* #ifdef WINDOWS_NT */
|
|
|
|
DelayTime = ((SetCounter (((struct{dword offset;word sel;}*)&pMGA)->sel)) >> 8);
|
|
PullDwClock (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime);
|
|
|
|
find = 0;
|
|
retries = 0;
|
|
while (retries < 16)
|
|
{
|
|
if (SendStart (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime) != 0)
|
|
{
|
|
WriteByte (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime,DEVICE_ID);
|
|
|
|
if (WaitAck (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime) != 0)
|
|
{
|
|
WriteByte (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime,STRT_ADDR);
|
|
|
|
if (WaitAck (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime) != 0)
|
|
{
|
|
if (SendStart (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime) != 0)
|
|
{
|
|
WriteByte (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime,(DEVICE_ID | 1));
|
|
|
|
if (WaitAck (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime) != 0)
|
|
{
|
|
for (i = 0; i < 127; i++)
|
|
{
|
|
((byte *)&DataEdid)[i] = ReadByte (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime);
|
|
SendAck (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime);
|
|
}
|
|
((byte *)&DataEdid)[i] = ReadByte (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime);
|
|
|
|
find = FindHeader((byte *)&DataEdid);
|
|
SendStop (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime);
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
SendStop (((struct{dword offset;word sel;}*)&pMGA)->sel,DelayTime);
|
|
}
|
|
retries++;
|
|
}
|
|
|
|
|
|
if (!find)
|
|
{
|
|
if (DetectSDA(((struct{dword offset;word sel;}*) &pMGA)->sel))
|
|
{
|
|
EditCRTCReg(BACKUP);
|
|
ScreenOff();
|
|
Boost_Vsync();
|
|
|
|
ScanSDA(((struct{dword offset;word sel;}*) &pMGA)->sel,
|
|
((struct{dword offset;word sel;}*) &EdidBuffer)->sel,
|
|
((struct{dword offset;word sel;}*) &EdidBuffer)->offset );
|
|
|
|
find = ExtractEdid(EdidBuffer);
|
|
EditCRTCReg(RESTORE);
|
|
ScreenOn();
|
|
}
|
|
}
|
|
|
|
#endif /* #ifdef WINDOWS_NT */
|
|
#endif /* #ifdef WIN31 */
|
|
|
|
if (find)
|
|
{
|
|
if( DataEdid.established_timings.est_timings_I & 0x20 )
|
|
VBoardVesaParam[iBoard].VesaParam[2].Support = TRUE; /* 640X480X60Hz */
|
|
if( DataEdid.established_timings.est_timings_I & 0x08 )
|
|
VBoardVesaParam[iBoard].VesaParam[1].Support = TRUE; /* 640X480X72Hz */
|
|
if( DataEdid.established_timings.est_timings_I & 0x04 )
|
|
VBoardVesaParam[iBoard].VesaParam[0].Support = TRUE; /* 640X480X75Hz */
|
|
if( DataEdid.established_timings.est_timings_I & 0x02 )
|
|
VBoardVesaParam[iBoard].VesaParam[6].Support = TRUE; /* 800X600X56Hz */
|
|
if( DataEdid.established_timings.est_timings_I & 0x01 )
|
|
VBoardVesaParam[iBoard].VesaParam[5].Support = TRUE; /* 800X600X60Hz */
|
|
if( DataEdid.established_timings.est_timings_II & 0x80 )
|
|
VBoardVesaParam[iBoard].VesaParam[4].Support = TRUE; /* 800X600X72Hz */
|
|
if( DataEdid.established_timings.est_timings_II & 0x40 )
|
|
VBoardVesaParam[iBoard].VesaParam[3].Support = TRUE; /* 800X600X75Hz */
|
|
if( DataEdid.established_timings.est_timings_II & 0x10 )
|
|
VBoardVesaParam[iBoard].VesaParam[10].Support = TRUE;/* 1024X768X87Hz I */
|
|
if( DataEdid.established_timings.est_timings_II & 0x08 )
|
|
VBoardVesaParam[iBoard].VesaParam[9].Support = TRUE; /* 1024X768X60Hz */
|
|
if( DataEdid.established_timings.est_timings_II & 0x04 )
|
|
VBoardVesaParam[iBoard].VesaParam[8].Support = TRUE;/* 1024X768X70Hz */
|
|
if( DataEdid.established_timings.est_timings_II & 0x02 )
|
|
VBoardVesaParam[iBoard].VesaParam[7].Support = TRUE; /* 1024X768X75Hz */
|
|
if( DataEdid.established_timings.est_timings_II & 0x01 )
|
|
VBoardVesaParam[iBoard].VesaParam[11].Support = TRUE;/* 1280X1024X75Hz */
|
|
}
|
|
|
|
|
|
if (find)
|
|
{
|
|
/* first detailed timing */
|
|
|
|
#define TIMINGS0 VBoardVesaParam[iBoard].VesaParam[14].VideoSet[0]
|
|
#define DET_TIM0 DataEdid.detailed_timing[0]
|
|
|
|
TIMINGS0.PixClock = DET_TIM0.pixel_clock * 10L;
|
|
|
|
TIMINGS0.HDisp = ((short)DET_TIM0.ratio_hor & 0x00f0) << 4 | DET_TIM0.h_active;
|
|
|
|
TIMINGS0.HFPorch = (((short)DET_TIM0.mix & 0x00C0) << 2 | DET_TIM0.h_sync_offset)
|
|
- DET_TIM0.h_border;
|
|
|
|
TIMINGS0.HSync = ((short)DET_TIM0.mix & 0x0030) << 4 | DET_TIM0.h_sync_pulse_width;
|
|
|
|
TIMINGS0.HBPorch = (((short)DET_TIM0.ratio_hor & 0x000f) << 8 | DET_TIM0.h_blanking)
|
|
- TIMINGS0.HSync - TIMINGS0.HFPorch - 2 * DET_TIM0.h_border;
|
|
|
|
TIMINGS0.HOvscan = DET_TIM0.h_border;
|
|
|
|
TIMINGS0.VDisp = ((short)DET_TIM0.ratio_vert & 0x00f0) << 4 | DET_TIM0.v_active;
|
|
|
|
TIMINGS0.VFPorch = ((short)(DET_TIM0.mix & 0x000C) << 2 | (DET_TIM0.ratio_sync & 0x00f0) >> 4)
|
|
- DET_TIM0.v_border;
|
|
|
|
TIMINGS0.VSync = ((short)(DET_TIM0.mix & 0x0003) << 4) | (DET_TIM0.ratio_sync & 0x000f);
|
|
|
|
TIMINGS0.VBPorch = (((short)DET_TIM0.ratio_vert & 0x000f) << 8 | DET_TIM0.v_blanking) -
|
|
TIMINGS0.VSync - TIMINGS0.VFPorch - 2 * DET_TIM0.v_border;
|
|
|
|
TIMINGS0.VOvscan = DET_TIM0.v_border;
|
|
|
|
TIMINGS0.OvscanEnable = 0;
|
|
|
|
TIMINGS0.InterlaceEnable = (DET_TIM0.flags & 0x80) >> 7;
|
|
|
|
TIMINGS0.HsyncPol = ((DET_TIM0.flags & 0x18) == 0x18) ? (DET_TIM0.flags & 0x02) >> 1 : 0;
|
|
|
|
TIMINGS0.VsyncPol = ((DET_TIM0.flags & 0x18) == 0x18) ? (DET_TIM0.flags & 0x04) >> 2 : 0;
|
|
|
|
/* copy the VideoSet for zoom by 1 to the others VideoSet assuming */
|
|
/* the video parameters are the same if we zoom */
|
|
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[14].VideoSet[1],&TIMINGS0,sizeof(Vidset));
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[14].VideoSet[2],&TIMINGS0,sizeof(Vidset));
|
|
|
|
if ((VBoardVesaParam[iBoard].VesaParam[14].DispWidth = TIMINGS0.HDisp) != 0
|
|
&&(VBoardVesaParam[iBoard].VesaParam[14].DispHeight = TIMINGS0.VDisp) != 0)
|
|
{
|
|
long Htotal;
|
|
long Vtotal;
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[14].DispHeight = TIMINGS0.VDisp;
|
|
|
|
/* To calculate the refresh rate use */
|
|
/* Rate = PixelClock * 10000 / (Htotal * Vtotal) */
|
|
|
|
Htotal = (((word)DET_TIM0.ratio_hor & 0x00f0) << 4
|
|
| DET_TIM0.h_active) + (((word)DET_TIM0.ratio_hor & 0x000f) << 8
|
|
| DET_TIM0.h_blanking);
|
|
|
|
Vtotal = (((word)DET_TIM0.ratio_vert & 0x00f0) << 4
|
|
| DET_TIM0.v_active) + (((word)DET_TIM0.ratio_vert & 0x000f) << 8
|
|
| DET_TIM0.v_blanking);
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[14].RefreshRate =
|
|
(word)((DET_TIM0.pixel_clock * 10000L) / (Htotal * Vtotal));
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[14].Support = 1;
|
|
}
|
|
|
|
|
|
/* second detailed timing */
|
|
|
|
#define TIMINGS1 VBoardVesaParam[iBoard].VesaParam[15].VideoSet[0]
|
|
#define DET_TIM1 DataEdid.detailed_timing[1]
|
|
|
|
TIMINGS1.PixClock = DET_TIM1.pixel_clock * 10L;
|
|
|
|
TIMINGS1.HDisp = ((short)DET_TIM1.ratio_hor & 0x00f0) << 4
|
|
| DET_TIM1.h_active;
|
|
|
|
TIMINGS1.HFPorch = (((short)DET_TIM1.mix & 0x00C0) << 2
|
|
| DET_TIM1.h_sync_offset) - DET_TIM1.h_border;
|
|
|
|
TIMINGS1.HSync = ((short)DET_TIM1.mix & 0x0030) << 4
|
|
| DET_TIM1.h_sync_pulse_width;
|
|
|
|
TIMINGS1.HBPorch = (((short)DET_TIM1.ratio_hor & 0x000f) << 8
|
|
| DET_TIM1.h_blanking) - TIMINGS1.HSync - TIMINGS1.HFPorch
|
|
- 2 * DET_TIM1.h_border;
|
|
|
|
TIMINGS1.HOvscan = DET_TIM1.h_border;
|
|
|
|
TIMINGS1.VDisp = ((short)DET_TIM1.ratio_vert & 0x00f0) << 4
|
|
| DET_TIM1.v_active;
|
|
|
|
TIMINGS1.VFPorch = ((short)(DET_TIM1.mix & 0x000C) << 2
|
|
| (DET_TIM1.ratio_sync & 0x00f0) >> 4) - DET_TIM1.v_border;
|
|
|
|
TIMINGS1.VSync = ((short)(DET_TIM1.mix & 0x0003) << 4)
|
|
| (DET_TIM1.ratio_sync & 0x000f);
|
|
|
|
TIMINGS1.VBPorch = (((short)DET_TIM1.ratio_vert & 0x000f) << 8
|
|
| DET_TIM1.v_blanking) - TIMINGS1.VSync - TIMINGS1.VFPorch
|
|
- 2 * DET_TIM1.v_border;
|
|
|
|
TIMINGS1.VOvscan = DET_TIM1.v_border;
|
|
|
|
TIMINGS1.OvscanEnable = 0;
|
|
|
|
TIMINGS1.InterlaceEnable = (DET_TIM1.flags & 0x80) >> 7;
|
|
|
|
TIMINGS1.HsyncPol = ((DET_TIM1.flags & 0x18) == 0x18)
|
|
? (DET_TIM1.flags & 0x02) >> 1 : 0;
|
|
|
|
TIMINGS1.VsyncPol = ((DET_TIM1.flags & 0x18) == 0x18)
|
|
? (DET_TIM1.flags & 0x04) >> 2 : 0;
|
|
|
|
/* copy the VideoSet for zoom by 1 to the others VideoSet assuming */
|
|
/* the video parameters are the same if we zoom */
|
|
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[15].VideoSet[1],&TIMINGS1,sizeof(Vidset));
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[15].VideoSet[2],&TIMINGS1,sizeof(Vidset));
|
|
|
|
if ((VBoardVesaParam[iBoard].VesaParam[15].DispWidth = TIMINGS1.HDisp) != 0
|
|
&&(VBoardVesaParam[iBoard].VesaParam[15].DispHeight = TIMINGS1.VDisp) != 0)
|
|
{
|
|
long Htotal;
|
|
long Vtotal;
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[15].DispHeight = TIMINGS1.VDisp;
|
|
|
|
/* To calculate the refresh rate use */
|
|
/* Rate = PixelClock * 10000 / (Htotal * Vtotal) */
|
|
|
|
Htotal = (((word)DET_TIM1.ratio_hor & 0x00f0) << 4
|
|
| DET_TIM1.h_active) + (((word)DET_TIM1.ratio_hor & 0x000f) << 8
|
|
| DET_TIM1.h_blanking);
|
|
|
|
Vtotal = (((word)DET_TIM1.ratio_vert & 0x00f0) << 4
|
|
| DET_TIM1.v_active) + (((word)DET_TIM1.ratio_vert & 0x000f) << 8
|
|
| DET_TIM1.v_blanking);
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[15].RefreshRate =
|
|
(word)((DET_TIM1.pixel_clock * 10000L) / (Htotal * Vtotal));
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[15].Support = 1;
|
|
}
|
|
|
|
/* third detailed timing */
|
|
|
|
#define TIMINGS2 VBoardVesaParam[iBoard].VesaParam[16].VideoSet[0]
|
|
#define DET_TIM2 DataEdid.detailed_timing[2]
|
|
|
|
TIMINGS2.PixClock = DET_TIM2.pixel_clock * 10L;
|
|
|
|
TIMINGS2.HDisp = ((short)DET_TIM2.ratio_hor & 0x00f0) << 4
|
|
| DET_TIM2.h_active;
|
|
|
|
TIMINGS2.HFPorch = (((short)DET_TIM2.mix & 0x00C0) << 2
|
|
| DET_TIM2.h_sync_offset) - DET_TIM2.h_border;
|
|
|
|
TIMINGS2.HSync = ((short)DET_TIM2.mix & 0x0030) << 4
|
|
| DET_TIM2.h_sync_pulse_width;
|
|
|
|
TIMINGS2.HBPorch = (((short)DET_TIM2.ratio_hor & 0x000f) << 8
|
|
| DET_TIM2.h_blanking) - TIMINGS2.HSync - TIMINGS2.HFPorch
|
|
- 2 * DET_TIM2.h_border;
|
|
|
|
TIMINGS2.HOvscan = DET_TIM2.h_border;
|
|
|
|
TIMINGS2.VDisp = ((short)DET_TIM2.ratio_vert & 0x00f0) << 4
|
|
| DET_TIM2.v_active;
|
|
|
|
TIMINGS2.VFPorch = ((short)(DET_TIM2.mix & 0x000C) << 2
|
|
| (DET_TIM2.ratio_sync & 0x00f0) >> 4) - DET_TIM2.v_border;
|
|
|
|
TIMINGS2.VSync = ((short)(DET_TIM2.mix & 0x0003) << 4)
|
|
| (DET_TIM2.ratio_sync & 0x000f);
|
|
|
|
TIMINGS2.VBPorch = (((short)DET_TIM2.ratio_vert & 0x000f) << 8
|
|
| DET_TIM2.v_blanking) - TIMINGS2.VSync - TIMINGS2.VFPorch
|
|
- 2 * DET_TIM2.v_border;
|
|
|
|
TIMINGS2.VOvscan = DET_TIM2.v_border;
|
|
|
|
TIMINGS2.OvscanEnable = 0;
|
|
|
|
TIMINGS2.InterlaceEnable = (DET_TIM2.flags & 0x80) >> 7;
|
|
|
|
TIMINGS2.HsyncPol = ((DET_TIM2.flags & 0x18) == 0x18)
|
|
? (DET_TIM2.flags & 0x02) >> 1 : 0;
|
|
|
|
TIMINGS2.VsyncPol = ((DET_TIM2.flags & 0x18) == 0x18)
|
|
? (DET_TIM2.flags & 0x04) >> 2: 0;
|
|
|
|
/* copy the VideoSet for zoom by 1 to the others VideoSet assuming */
|
|
/* the video parameters are the same if we zoom */
|
|
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[16].VideoSet[1],&TIMINGS2,sizeof(Vidset));
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[16].VideoSet[2],&TIMINGS2,sizeof(Vidset));
|
|
|
|
if ((VBoardVesaParam[iBoard].VesaParam[16].DispWidth = TIMINGS2.HDisp) != 0
|
|
&&(VBoardVesaParam[iBoard].VesaParam[16].DispHeight = TIMINGS2.VDisp) != 0)
|
|
{
|
|
long Htotal;
|
|
long Vtotal;
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[16].DispHeight = TIMINGS2.VDisp;
|
|
|
|
/* To calculate the refresh rate use */
|
|
/* Rate = PixelClock * 10000 / (Htotal * Vtotal) */
|
|
|
|
Htotal = (((word)DET_TIM2.ratio_hor & 0x00f0) << 4
|
|
| DET_TIM2.h_active) + (((word)DET_TIM2.ratio_hor & 0x000f) << 8
|
|
| DET_TIM2.h_blanking);
|
|
|
|
Vtotal = (((word)DET_TIM2.ratio_vert & 0x00f0) << 4
|
|
| DET_TIM2.v_active) + (((word)DET_TIM2.ratio_vert & 0x000f) << 8
|
|
| DET_TIM2.v_blanking);
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[16].RefreshRate =
|
|
(word)((DET_TIM2.pixel_clock * 10000L) / (Htotal * Vtotal));
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[16].Support = 1;
|
|
}
|
|
|
|
/* fourth detailed timing */
|
|
|
|
#define TIMINGS3 VBoardVesaParam[iBoard].VesaParam[17].VideoSet[0]
|
|
#define DET_TIM3 DataEdid.detailed_timing[3]
|
|
|
|
TIMINGS3.PixClock = DET_TIM3.pixel_clock * 10L;
|
|
|
|
TIMINGS3.HDisp = ((short)DET_TIM3.ratio_hor & 0x00f0) << 4
|
|
| DET_TIM3.h_active;
|
|
|
|
TIMINGS3.HFPorch = (((short)DET_TIM3.mix & 0x00C0) << 2
|
|
| DET_TIM3.h_sync_offset) - DET_TIM3.h_border;
|
|
|
|
TIMINGS3.HSync = ((short)DET_TIM3.mix & 0x0030) << 4
|
|
| DET_TIM3.h_sync_pulse_width;
|
|
|
|
TIMINGS3.HBPorch = (((short)DET_TIM3.ratio_hor & 0x000f) << 8
|
|
| DET_TIM3.h_blanking) - TIMINGS3.HSync - TIMINGS3.HFPorch
|
|
- 2 * DET_TIM3.h_border;
|
|
|
|
TIMINGS3.HOvscan = DET_TIM3.h_border;
|
|
|
|
TIMINGS3.VDisp = ((short)DET_TIM3.ratio_vert & 0x00f0) << 4
|
|
| DET_TIM3.v_active;
|
|
|
|
TIMINGS3.VFPorch = ((short)(DET_TIM3.mix & 0x000C) << 2
|
|
| (DET_TIM3.ratio_sync & 0x00f0) >> 4) - DET_TIM3.v_border;
|
|
|
|
TIMINGS3.VSync = ((short)(DET_TIM3.mix & 0x0003) << 4)
|
|
| (DET_TIM3.ratio_sync & 0x000f);
|
|
|
|
TIMINGS3.VBPorch = (((short)DET_TIM3.ratio_vert & 0x000f) << 8
|
|
| DET_TIM3.v_blanking) - TIMINGS3.VSync - TIMINGS3.VFPorch
|
|
- 2 * DET_TIM3.v_border;
|
|
|
|
TIMINGS3.VOvscan = DET_TIM3.v_border;
|
|
|
|
TIMINGS3.OvscanEnable = 0;
|
|
|
|
TIMINGS3.InterlaceEnable = (DET_TIM3.flags & 0x80) >> 7;
|
|
|
|
TIMINGS3.HsyncPol = ((DET_TIM3.flags & 0x18) == 0x18)
|
|
? (DET_TIM3.flags & 0x02) >> 1 : 0;
|
|
|
|
TIMINGS3.VsyncPol = ((DET_TIM3.flags & 0x18) == 0x18)
|
|
? (DET_TIM3.flags & 0x04) >> 2 : 0;
|
|
|
|
/* copy the VideoSet for zoom by 1 to the others VideoSet assuming */
|
|
/* the video parameters are the same if we zoom */
|
|
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[17].VideoSet[1],&TIMINGS3,sizeof(Vidset));
|
|
memcpy(&VBoardVesaParam[iBoard].VesaParam[17].VideoSet[2],&TIMINGS3,sizeof(Vidset));
|
|
|
|
if ((VBoardVesaParam[iBoard].VesaParam[17].DispWidth = TIMINGS3.HDisp) != 0
|
|
&&(VBoardVesaParam[iBoard].VesaParam[17].DispHeight = TIMINGS3.VDisp) != 0)
|
|
{
|
|
long Htotal;
|
|
long Vtotal;
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[17].DispHeight = TIMINGS3.VDisp;
|
|
|
|
/* To calculate the refresh rate use */
|
|
/* Rate = PixelClock * 10000 / (Htotal * Vtotal) */
|
|
|
|
Htotal = (((word)DET_TIM1.ratio_hor & 0x00f0) << 4
|
|
| DET_TIM3.h_active) + (((word)DET_TIM3.ratio_hor & 0x000f) << 8
|
|
| DET_TIM3.h_blanking);
|
|
|
|
Vtotal = (((word)DET_TIM3.ratio_vert & 0x00f0) << 4
|
|
| DET_TIM3.v_active) + (((word)DET_TIM3.ratio_vert & 0x000f) << 8
|
|
| DET_TIM3.v_blanking);
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[17].RefreshRate =
|
|
(word)((DET_TIM3.pixel_clock * 10000L) / (Htotal * Vtotal));
|
|
|
|
VBoardVesaParam[iBoard].VesaParam[17].Support = 1;
|
|
}
|
|
|
|
// Add1152Timings();
|
|
}
|
|
|
|
#if DEBUG
|
|
{
|
|
int i;
|
|
for (i = 0; i < 128; i++)
|
|
{
|
|
if (!(i%8))
|
|
printf ("\n");
|
|
printf (" %02x ",((byte *)&DataEdid)[i]);
|
|
}
|
|
printf ("\n");
|
|
getch();
|
|
}
|
|
|
|
{
|
|
int i,j;
|
|
|
|
for (i = 14; i < 18; i++)
|
|
{
|
|
for (j = 0; j < 3; j++)
|
|
{
|
|
printf ("\n Dispwith = %d",VBoardVesaParam[iBoard].VesaParam[i].DispWidth);
|
|
printf ("\n Height = %d",VBoardVesaParam[iBoard].VesaParam[i].DispHeight);
|
|
printf ("\n RefreshRate = %d",VBoardVesaParam[iBoard].VesaParam[i].RefreshRate);
|
|
printf ("\n Support = %d",VBoardVesaParam[iBoard].VesaParam[i].Support);
|
|
printf ("\n Clock = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].PixClock);
|
|
printf ("\n HDisp = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].HDisp);
|
|
printf ("\n HFPorch = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].HFPorch);
|
|
printf ("\n Hsync = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].HSync);
|
|
printf ("\n HbPorch = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].HBPorch);
|
|
printf ("\n Hovscan = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].HOvscan);
|
|
printf ("\n VDisp = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].VDisp);
|
|
printf ("\n VFPorch = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].VFPorch);
|
|
printf ("\n Vsync = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].VSync);
|
|
printf ("\n VbPorch = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].VBPorch);
|
|
printf ("\n Vovscan = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].VOvscan);
|
|
printf ("\n Vovscanenable = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].OvscanEnable);
|
|
printf ("\n Inter = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].InterlaceEnable);
|
|
printf ("\n Hsyncpol = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].HsyncPol);
|
|
printf ("\n Vsyncpol = %ld",VBoardVesaParam[iBoard].VesaParam[i].VideoSet[j].VsyncPol);
|
|
printf ("\n");
|
|
getch();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return (find);
|
|
}
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : InDDCTable
|
|
*
|
|
* description : This function verifies if the current resolution is
|
|
* present in the DDC table receive from the monitor.
|
|
*
|
|
* Return: TRUE = if the resolution is present in the table
|
|
* FALSE = if the resolution is not present in the table
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
byte InDDCTable(dword DispWidth)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; VBoardVesaParam[iBoard].VesaParam[i].DispWidth != (word) -1; i++)
|
|
if (VBoardVesaParam[iBoard].VesaParam[i].DispWidth == DispWidth
|
|
&& VBoardVesaParam[iBoard].VesaParam[i].Support)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : FindDDCFreq
|
|
*
|
|
* description : This function returns the best refresh rate and the
|
|
* corresponding video set of the desired resolution.
|
|
*
|
|
* Return: DDCVideoSet the video set of the resolution
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
Vidset *FindDDCFreq(dword DispWidth)
|
|
{
|
|
int i;
|
|
word RefreshRate;
|
|
Vidset *DDCVideoSet;
|
|
|
|
DDCVideoSet = NULL;
|
|
RefreshRate = 0;
|
|
for (i = 0; VBoardVesaParam[iBoard].VesaParam[i].DispWidth != (word) -1; i++)
|
|
{
|
|
if (VBoardVesaParam[iBoard].VesaParam[i].DispWidth == DispWidth
|
|
&& VBoardVesaParam[iBoard].VesaParam[i].Support
|
|
&& VBoardVesaParam[iBoard].VesaParam[i].RefreshRate > RefreshRate)
|
|
{
|
|
RefreshRate = VBoardVesaParam[iBoard].VesaParam[i].RefreshRate;
|
|
DDCVideoSet = VBoardVesaParam[iBoard].VesaParam[i].VideoSet;
|
|
}
|
|
}
|
|
|
|
return (DDCVideoSet);
|
|
}
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : Add1152Timings
|
|
*
|
|
* description : This functions adds the 1152 x 882 resolution
|
|
* in the case where the 1280 x 1024 resolution
|
|
* are supported.
|
|
*
|
|
* Return: NONE
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
void Add1152Timings(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; VBoardVesaParam[iBoard].VesaParam[i].DispWidth != (word) -1; i++)
|
|
{
|
|
if (VBoardVesaParam[iBoard].VesaParam[i].DispWidth >= 1280
|
|
&& VBoardVesaParam[iBoard].VesaParam[i].Support)
|
|
{
|
|
for (i = 0; VBoardVesaParam[iBoard].VesaParam[i].DispWidth != (word) -1; i++)
|
|
{
|
|
if (VBoardVesaParam[iBoard].VesaParam[i].DispWidth == 1152)
|
|
VBoardVesaParam[iBoard].VesaParam[i].Support = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : ExtractEdid
|
|
*
|
|
* description : This function extract the parity bit of the Edid block
|
|
* information and verify if the Edid block header is present.
|
|
*
|
|
* Return: TRUE = if the information block is valid
|
|
* FALSE = if the information block is invalid
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
byte ExtractEdid(word *buffer)
|
|
{
|
|
byte found;
|
|
word i,j;
|
|
word temp1,temp2;
|
|
|
|
found = FALSE;
|
|
for (j = 0; (j < 9) && !found; j++)
|
|
{
|
|
for (i = 0; i < 128; i++)
|
|
{
|
|
temp1 = temp2 = buffer[i];
|
|
temp1 &= (0xffff << (j + 1));
|
|
temp1 >>= 1;
|
|
temp2 &= (0xffff >> (16 - j));
|
|
temp1 |= temp2;
|
|
((byte *) &DataEdid)[i] = (byte) temp1;
|
|
}
|
|
found = FindHeader ((byte *)&DataEdid);
|
|
}
|
|
|
|
return (found);
|
|
}
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : FindHeader
|
|
*
|
|
* description : This function verify if the Edid block contains the DDC
|
|
* header.
|
|
*
|
|
* Return: TRUE = if we have found the header
|
|
* FALSE = if we have not found the header
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
byte FindHeader(byte *buffer)
|
|
{
|
|
byte found,bitin,bitout;
|
|
word i,k;
|
|
sword j;
|
|
byte Header[] = {0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00};
|
|
|
|
found = FALSE;
|
|
for (i = 0; (i < 1024) && !found; i++)
|
|
{
|
|
found = TRUE;
|
|
for (k = 0; k < 8; k++)
|
|
{
|
|
if (buffer[k] != Header[k])
|
|
found = FALSE;
|
|
}
|
|
|
|
for (j = 127; j >= 0 && !found; j--)
|
|
{
|
|
if (j == 127)
|
|
{
|
|
bitout = buffer[j] & 0x80;
|
|
bitout >>= 7;
|
|
bitin = buffer[0] & 0x80;
|
|
bitin >>= 7;
|
|
buffer[j] <<= 1;
|
|
buffer[j] |= bitin;
|
|
bitin = bitout;
|
|
}
|
|
else
|
|
{
|
|
bitout = buffer[j] & 0x80;
|
|
bitout >>= 7;
|
|
buffer[j] <<= 1;
|
|
buffer[j] |= bitin;
|
|
bitin = bitout;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (found);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : Boost_Vsync
|
|
*
|
|
* description : This function change the CRTC parameters to
|
|
* boost the Vsync frequency to 2kHz.
|
|
*
|
|
* Return: NONE
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
void Boost_Vsync(void)
|
|
{
|
|
word i,tmpbyte;
|
|
|
|
struct CRTCTable
|
|
{
|
|
byte index;
|
|
byte data; /* 2 khz */
|
|
} CRTCVal[] = {{0x00,0x10},
|
|
{0x02,0x10},
|
|
{0x03,0x06},
|
|
{0x04,0x00},
|
|
{0x05,0x01},
|
|
{0x06,0x47},
|
|
{0x07,0x00},
|
|
{0x10,0x00},
|
|
{0x11,0x0f},
|
|
{0x15,0x10},
|
|
{0x16,0x06},
|
|
{0x17,0x80},
|
|
{0xff,0xff},
|
|
};
|
|
|
|
/* Unlock the CRTC registers */
|
|
mgaWriteBYTE (*(pMGA + STORM_OFFSET + VGA_CRTC_INDEX),(unsigned char)0x11);
|
|
mgaReadBYTE (*(pMGA + STORM_OFFSET + VGA_CRTC_DATA),tmpbyte);
|
|
tmpbyte &= 0x7f;
|
|
mgaWriteBYTE (*(pMGA + STORM_OFFSET + VGA_CRTC_DATA),(byte)tmpbyte);
|
|
|
|
/* Load the CRTC values */
|
|
for (i = 0; CRTCVal[i].index != 0xff; i++)
|
|
{
|
|
mgaWriteBYTE(*(pMGA + STORM_OFFSET + VGA_CRTC_INDEX),CRTCVal[i].index);
|
|
mgaWriteBYTE(*(pMGA + STORM_OFFSET + VGA_CRTC_DATA),CRTCVal[i].data);
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------
|
|
*
|
|
* name : EditCRTCReg
|
|
*
|
|
* description : This function can take two actions on the
|
|
* CRTC registers. It can backup the values of
|
|
* the registers or restore it.
|
|
*
|
|
* Return: NONE
|
|
*
|
|
*------------------------------------------------------*/
|
|
|
|
void EditCRTCReg(enum CRTCaction action)
|
|
{
|
|
byte i,tmpbyte;
|
|
|
|
/* Unlock the CRTC registers */
|
|
mgaWriteBYTE (*(pMGA + STORM_OFFSET + VGA_CRTC_INDEX),(unsigned char)0x11);
|
|
mgaReadBYTE (*(pMGA + STORM_OFFSET + VGA_CRTC_DATA),tmpbyte);
|
|
tmpbyte &= 0x7f;
|
|
mgaWriteBYTE (*(pMGA + STORM_OFFSET + VGA_CRTC_DATA),tmpbyte);
|
|
|
|
if (action == BACKUP)
|
|
{
|
|
/* Read the CRTC values */
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
mgaWriteBYTE(*(pMGA + STORM_OFFSET + VGA_CRTC_INDEX),i);
|
|
mgaReadBYTE(*(pMGA + STORM_OFFSET + VGA_CRTC_DATA),CRTCValReg[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Load the CRTC values */
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
mgaWriteBYTE(*(pMGA + STORM_OFFSET + VGA_CRTC_INDEX),i);
|
|
mgaWriteBYTE(*(pMGA + STORM_OFFSET + VGA_CRTC_DATA),CRTCValReg[i]);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WINDOWS_NT
|
|
|
|
// Macro to wait for the beginning of a VSync.
|
|
|
|
#define WaitForVSyncStart(pBoardRegs) \
|
|
mgaPollBYTE(*(pBoardRegs + STORM_OFFSET + STORM_STATUS),0x00,0x08); \
|
|
mgaPollBYTE(*(pBoardRegs + STORM_OFFSET + STORM_STATUS),0x08,0x08)
|
|
|
|
// Macro to measure the length of a VSync cycle.
|
|
|
|
#if !defined(MGA_ALPHA)
|
|
#define EstimateVSyncCycle(pBoardRegs, ulCounter) \
|
|
ulCounter = 0; \
|
|
do \
|
|
{ \
|
|
ulCounter++; \
|
|
} while ((*((volatile UCHAR *)(pBoardRegs + STORM_OFFSET + \
|
|
STORM_STATUS)) & 0x08) != 0); \
|
|
do \
|
|
{ \
|
|
ulCounter++; \
|
|
} while ((*((volatile UCHAR *)(pBoardRegs + STORM_OFFSET + \
|
|
STORM_STATUS)) & 0x08) != 0x08)
|
|
#else /* #if !defined(MGA_ALPHA) */
|
|
#define EstimateVSyncCycle(pBoardRegs, ulCounter) \
|
|
ulCounter = 0; \
|
|
do \
|
|
{ \
|
|
ulCounter++; \
|
|
} while ((VideoPortReadRegisterUchar((PUCHAR)(pBoardRegs + \
|
|
STORM_OFFSET + STORM_STATUS)) & 0x08) != 0); \
|
|
do \
|
|
{ \
|
|
ulCounter++; \
|
|
} while ((VideoPortReadRegisterUchar((PUCHAR)(pBoardRegs + \
|
|
STORM_OFFSET + STORM_STATUS)) & 0x08) != 0x08)
|
|
#endif /* #if !defined(MGA_ALPHA) */
|
|
|
|
// Macro to wait a set delay through a VSync cycle.
|
|
|
|
#if !defined(MGA_ALPHA)
|
|
// There are always null bits in STORM_STATUS low nibble, so that this
|
|
// part of the test is always true.
|
|
#define WaitThroughVSyncCycle(pBoardRegs, ulCounter) \
|
|
do \
|
|
{ \
|
|
ulCounter--; \
|
|
} while ((ulCounter != 0) && \
|
|
(*((volatile UCHAR *)(pBoardRegs + STORM_OFFSET + \
|
|
STORM_STATUS)) & 0xFF) != 0xFF)
|
|
#else /* #if !defined(MGA_ALPHA) */
|
|
#define WaitThroughVSyncCycle(pBoardRegs, ulCounter) \
|
|
do \
|
|
{ \
|
|
ulCounter--; \
|
|
} while ((ulCounter != 0) && \
|
|
(VideoPortReadRegisterUchar((PUCHAR)(pBoardRegs + \
|
|
STORM_OFFSET + STORM_STATUS)) & 0xFF) != 0xFF)
|
|
#endif /* #if !defined(MGA_ALPHA) */
|
|
|
|
|
|
/****************************************************************************
|
|
* Functions converted from DDCCOMM.ASM
|
|
****************************************************************************/
|
|
|
|
ULONG SetCounter(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
ULONG ulCounter;
|
|
|
|
WaitForVSyncStart(pBoardRegs);
|
|
|
|
// We are now at the beginning of the vsync cycle. Increment a counter
|
|
// so we can estimate the length of a cycle.
|
|
EstimateVSyncCycle(pBoardRegs, ulCounter);
|
|
return(ulCounter);
|
|
}
|
|
|
|
VOID SetScl(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
UCHAR ucByte;
|
|
|
|
// Define the SCL as an output.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_CTL);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte |= 0x10;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
|
|
// Write a 1 on the SCL line.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_DATA);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte |= 0x10;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
}
|
|
|
|
VOID SetSda(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
UCHAR ucByte;
|
|
|
|
// Define the SDA as an output.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_CTL);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte |= 0x04;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
|
|
// Write a 1 on the SDA line.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_DATA);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte |= 0x04;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
}
|
|
|
|
VOID ClrScl(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
UCHAR ucByte;
|
|
|
|
// Define the SCL as an output.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_CTL);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte |= 0x10;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
|
|
// Write a 1 on the SCL line.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_DATA);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte &= ~0x10;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
}
|
|
|
|
VOID ClrSda(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
UCHAR ucByte;
|
|
|
|
// Define the SDA as an output.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_CTL);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte |= 0x04;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
|
|
// Write a 1 on the SDA line.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_DATA);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte &= ~0x04;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
}
|
|
|
|
UCHAR ReadSda(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
UCHAR ucByte;
|
|
|
|
// Define the SDA as an input.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_CTL);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte &= 0x1b;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
|
|
// Get the result.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_DATA);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
return((ucByte & 0x04) >> 2);
|
|
}
|
|
|
|
UCHAR ReadScl(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
UCHAR ucByte;
|
|
|
|
// Define the SCL as an input.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_CTL);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
ucByte &= ~0x10;
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
|
|
// Get the result.
|
|
mgaWriteBYTE(*(pBoardRegs + RAMDAC_OFFSET + TVP3026_INDEX),
|
|
TVP3026_GEN_IO_DATA);
|
|
mgaReadBYTE (*(pBoardRegs + RAMDAC_OFFSET + TVP3026_DATA), ucByte);
|
|
return((ucByte & 0x10) >> 4);
|
|
}
|
|
|
|
VOID Delay(volatile byte _FAR *pBoardRegs, ULONG ulCounter)
|
|
{
|
|
WaitThroughVSyncCycle(pBoardRegs, ulCounter);
|
|
}
|
|
|
|
VOID PullDwClock(volatile byte _FAR *pBoardRegs, ULONG ulCounter)
|
|
{
|
|
ClrScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
}
|
|
|
|
UCHAR SendStart(volatile byte _FAR *pBoardRegs, ULONG ulCounter)
|
|
{
|
|
UCHAR ucCntr = 0xff;
|
|
|
|
SetSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
SetScl(pBoardRegs);
|
|
|
|
while (--ucCntr != 0)
|
|
{
|
|
Delay(pBoardRegs, ulCounter);
|
|
if (ReadScl(pBoardRegs) && ReadSda(pBoardRegs))
|
|
{
|
|
ClrSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
ClrScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
break;
|
|
}
|
|
}
|
|
return(ucCntr);
|
|
}
|
|
|
|
VOID SendStop(volatile byte _FAR *pBoardRegs, ULONG ulCounter)
|
|
{
|
|
ClrSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
ClrScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
SetScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
SetSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
}
|
|
|
|
UCHAR WaitAck(volatile byte _FAR *pBoardRegs, ULONG ulCounter)
|
|
{
|
|
UCHAR ucCntr;
|
|
|
|
SetSda(pBoardRegs);
|
|
ucCntr = 0xff;
|
|
|
|
do
|
|
{
|
|
Delay(pBoardRegs, ulCounter);
|
|
} while (ReadSda(pBoardRegs) && (--ucCntr != 0));
|
|
|
|
if (ucCntr == 0)
|
|
return(ucCntr);
|
|
|
|
SetScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
ClrScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
SetSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
|
|
return(ucCntr);
|
|
}
|
|
|
|
VOID SendAck(volatile byte _FAR *pBoardRegs, ULONG ulCounter)
|
|
{
|
|
ClrSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
SetScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
ClrScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
SetSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
}
|
|
|
|
VOID WriteByte(volatile byte _FAR *pBoardRegs, ULONG ulCounter, UCHAR ucData)
|
|
{
|
|
UCHAR i;
|
|
|
|
// Get the information in ucData and transmit it on the SDA line.
|
|
for (i = 8; i != 0 ; i--)
|
|
{
|
|
if (ucData & 0x80)
|
|
SetSda(pBoardRegs);
|
|
else
|
|
ClrSda(pBoardRegs);
|
|
ucData <<= 1;
|
|
Delay(pBoardRegs, ulCounter);
|
|
SetScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
ClrScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
}
|
|
SetSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
}
|
|
|
|
UCHAR ReadByte(volatile byte _FAR *pBoardRegs, ULONG ulCounter)
|
|
{
|
|
UCHAR i, ucData;
|
|
|
|
ucData = 0;
|
|
|
|
// Get the information from the SDA line.
|
|
for (i = 8; i != 0 ; i--)
|
|
{
|
|
do
|
|
{
|
|
SetScl(pBoardRegs);
|
|
} while (ReadScl(pBoardRegs) == 0);
|
|
|
|
ucData <<= 1;
|
|
ucData |= ReadSda(pBoardRegs);
|
|
|
|
Delay(pBoardRegs, ulCounter);
|
|
ClrScl(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
}
|
|
SetSda(pBoardRegs);
|
|
Delay(pBoardRegs, ulCounter);
|
|
return(ucData);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* BOOLEAN DetectSDA(volatile byte _FAR *pBoardRegs)
|
|
****************************************************************************/
|
|
|
|
BOOLEAN DetectSDA(volatile byte _FAR *pBoardRegs)
|
|
{
|
|
ULONG ulCounter, ulCounterStore;
|
|
UCHAR ucBitCount;
|
|
|
|
ucBitCount = 60;
|
|
ulCounter = SetCounter(pBoardRegs);
|
|
|
|
// To read correctly the SDA, we make sure that we read it halfway
|
|
// through the cycle after the clock rise.
|
|
ulCounter /= 2;
|
|
ulCounterStore = ulCounter;
|
|
|
|
LoopTop:
|
|
// Wait for a zero.
|
|
mgaPollBYTE(*(pBoardRegs + STORM_OFFSET + STORM_STATUS),0x00,0x08);
|
|
|
|
// Wait for a one.
|
|
mgaPollBYTE(*(pBoardRegs + STORM_OFFSET + STORM_STATUS),0x08,0x08);
|
|
|
|
// Now wait for the set delay.
|
|
ulCounter = ulCounterStore;
|
|
WaitThroughVSyncCycle(pBoardRegs, ulCounter);
|
|
|
|
// If we detect a zero from the SDA line, then the line is active,
|
|
// otherwise the line is connected to a pull-up and always +5V.
|
|
if (ReadSda(pBoardRegs))
|
|
{
|
|
// The longest serise of 1's we can encounter is 6 * 9 = 54,
|
|
// coming from the header. So we check 60 bits. This loop
|
|
// takes a second to test at 60 Hz.
|
|
if (ucBitCount--)
|
|
goto LoopTop;
|
|
else
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* VOID ScanSDA(volatile byte _FAR *pBoardRegs, word *Buffer, word *Dummy)
|
|
****************************************************************************/
|
|
|
|
VOID ScanSDA(volatile byte _FAR *pBoardRegs, word *Buffer, word *Dummy)
|
|
{
|
|
ULONG ulCounter, ulCounterStore;
|
|
word *pBuffer, tmpWord;
|
|
UCHAR ucCount;
|
|
CHAR cShift;
|
|
|
|
pBuffer = Buffer;
|
|
cShift = 8;
|
|
ucCount = 128;
|
|
ulCounter = SetCounter(pBoardRegs);
|
|
|
|
// To read correctly the SDA, we make sure that we read it halfway
|
|
// through the cycle after the clock rise.
|
|
ulCounter /= 2;
|
|
ulCounterStore = ulCounter;
|
|
|
|
LoopTop:
|
|
// Wait for a zero.
|
|
mgaPollBYTE(*(pBoardRegs + STORM_OFFSET + STORM_STATUS),0x00,0x08);
|
|
|
|
// Wait for a one.
|
|
mgaPollBYTE(*(pBoardRegs + STORM_OFFSET + STORM_STATUS),0x08,0x08);
|
|
|
|
// Now wait for the set delay.
|
|
ulCounter = ulCounterStore;
|
|
WaitThroughVSyncCycle(pBoardRegs, ulCounter);
|
|
|
|
// If we detect a zero from the SDA line, then the line is active,
|
|
// otherwise the line is connected to a pull-up and always +5V.
|
|
// Define SDA as the input.
|
|
tmpWord = (word)ReadSda(pBoardRegs);
|
|
tmpWord <<= cShift;
|
|
*pBuffer |= tmpWord;
|
|
|
|
// We decrement the value of the shift until we reach 0, then we
|
|
// increment the word and restart shifting from the end.
|
|
cShift--;
|
|
if (cShift < 0)
|
|
{
|
|
cShift = 8;
|
|
pBuffer++;
|
|
ucCount--;
|
|
}
|
|
|
|
if (ucCount)
|
|
goto LoopTop;
|
|
}
|
|
|
|
#endif /* #ifdef WINDOWS_NT */
|
|
#endif /* #ifndef DONT_USE_DDC */
|