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.
843 lines
22 KiB
843 lines
22 KiB
//***************************************************************************
|
|
//
|
|
// Module Name:
|
|
//
|
|
// power.c
|
|
//
|
|
// Abstract:
|
|
// This module contains the code that implements the Plug & Play and
|
|
// power management features
|
|
//
|
|
// Environment:
|
|
//
|
|
// Kernel mode
|
|
//
|
|
//
|
|
// Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
|
|
// Copyright (c) 1995-1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "permedia.h"
|
|
|
|
#define VESA_POWER_FUNCTION 0x4f10
|
|
#define VESA_POWER_ON 0x0000
|
|
#define VESA_POWER_STANDBY 0x0100
|
|
#define VESA_POWER_SUSPEND 0x0200
|
|
#define VESA_POWER_OFF 0x0400
|
|
#define VESA_GET_POWER_FUNC 0x0000
|
|
#define VESA_SET_POWER_FUNC 0x0001
|
|
#define VESA_STATUS_SUCCESS 0x004f
|
|
|
|
//
|
|
// all our IDs begin with 0x1357bd so they are readily identifiable as our own
|
|
//
|
|
|
|
#define P2_DDC_MONITOR (0x1357bd00)
|
|
#define P2_NONDDC_MONITOR (0x1357bd01)
|
|
|
|
BOOLEAN PowerOnReset( PHW_DEVICE_EXTENSION hwDeviceExtension );
|
|
VOID SaveDeviceState( PHW_DEVICE_EXTENSION hwDeviceExtension );
|
|
VOID RestoreDeviceState( PHW_DEVICE_EXTENSION hwDeviceExtension );
|
|
|
|
VOID I2CWriteClock(PVOID HwDeviceExtension, UCHAR data);
|
|
VOID I2CWriteData(PVOID HwDeviceExtension, UCHAR data);
|
|
BOOLEAN I2CReadClock(PVOID HwDeviceExtension);
|
|
BOOLEAN I2CReadData(PVOID HwDeviceExtension);
|
|
VOID I2CWaitVSync(PVOID HwDeviceExtension);
|
|
|
|
#if defined(ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE, PowerOnReset)
|
|
#pragma alloc_text(PAGE, SaveDeviceState)
|
|
#pragma alloc_text(PAGE, RestoreDeviceState)
|
|
#pragma alloc_text(PAGE, Permedia2GetPowerState)
|
|
#pragma alloc_text(PAGE, Permedia2SetPowerState)
|
|
#pragma alloc_text(PAGE, Permedia2GetChildDescriptor)
|
|
#pragma alloc_text(PAGE, I2CWriteClock)
|
|
#pragma alloc_text(PAGE, I2CWriteData)
|
|
#pragma alloc_text(PAGE, I2CReadClock)
|
|
#pragma alloc_text(PAGE, I2CReadData)
|
|
#pragma alloc_text(PAGE, I2CWaitVSync)
|
|
#endif
|
|
|
|
|
|
I2C_FNC_TABLE I2CFunctionTable =
|
|
{
|
|
sizeof(I2C_FNC_TABLE),
|
|
I2CWriteClock,
|
|
I2CWriteData,
|
|
I2CReadClock,
|
|
I2CReadData,
|
|
I2CWaitVSync,
|
|
NULL
|
|
};
|
|
|
|
|
|
VP_STATUS Permedia2GetPowerState (
|
|
PVOID HwDeviceExtension,
|
|
ULONG HwId,
|
|
PVIDEO_POWER_MANAGEMENT VideoPowerControl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns power state information.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to our hardware device extension structure.
|
|
|
|
HwId - Private unique 32 bit ID identifing the device.
|
|
|
|
VideoPowerControl - Points to a VIDEO_POWER_MANAGEMENT structure that
|
|
specifies the power state for which support is
|
|
being queried.
|
|
|
|
Return Value:
|
|
|
|
VP_STATUS value (NO_ERROR or error value)
|
|
|
|
--*/
|
|
|
|
{
|
|
VIDEO_X86_BIOS_ARGUMENTS biosArguments;
|
|
VP_STATUS status;
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetPowerState: hwId(%xh) state = %d\n",
|
|
(int)HwId, (int)VideoPowerControl->PowerState));
|
|
|
|
switch((int)HwId)
|
|
{
|
|
case P2_DDC_MONITOR:
|
|
case P2_NONDDC_MONITOR:
|
|
|
|
switch (VideoPowerControl->PowerState)
|
|
{
|
|
|
|
case VideoPowerOn:
|
|
case VideoPowerStandBy:
|
|
case VideoPowerSuspend:
|
|
case VideoPowerOff:
|
|
case VideoPowerHibernate:
|
|
case VideoPowerShutdown:
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
default:
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetPowerState: Unknown monitor PowerState(%xh)\n",
|
|
(int)VideoPowerControl->PowerState));
|
|
|
|
ASSERT(FALSE);
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
|
|
case DISPLAY_ADAPTER_HW_ID:
|
|
|
|
//
|
|
// only support ON at the moment
|
|
//
|
|
|
|
switch (VideoPowerControl->PowerState)
|
|
{
|
|
case VideoPowerOn:
|
|
case VideoPowerStandBy:
|
|
case VideoPowerSuspend:
|
|
case VideoPowerHibernate:
|
|
case VideoPowerShutdown:
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerOff:
|
|
|
|
if( hwDeviceExtension->HardwiredSubSystemId )
|
|
{
|
|
status = NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If SubSystemId is not hardwired in a read-only way,
|
|
// it is possible we'll see a different value when
|
|
// system comes back form S3 mode. This will cause
|
|
// problem since os will assume this is a different
|
|
// device
|
|
//
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetPowerState: VideoPowerOff is not suported by this card!\n"));
|
|
|
|
status = ERROR_INVALID_FUNCTION;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetPowerState: Unknown adapter PowerState(%xh)\n",
|
|
(int)VideoPowerControl->PowerState));
|
|
|
|
ASSERT(FALSE);
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
DEBUG_PRINT((1, "Permedia2GetPowerState: Unknown hwId(%xh)",
|
|
(int)HwId));
|
|
ASSERT(FALSE);
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetPowerState: returning %xh\n", status));
|
|
|
|
return(status);
|
|
}
|
|
|
|
VP_STATUS Permedia2SetPowerState (
|
|
PVOID HwDeviceExtension,
|
|
ULONG HwId,
|
|
PVIDEO_POWER_MANAGEMENT VideoPowerControl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the power state for a given device.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to our hardware device extension structure.
|
|
|
|
HwId - Private unique 32 bit ID identifing the device.
|
|
|
|
VideoPowerControl - Points to a VIDEO_POWER_MANAGEMENT structure that
|
|
specifies the power state to be set.
|
|
|
|
Return Value:
|
|
|
|
VP_STATUS value (NO_ERROR, if all's well)
|
|
|
|
--*/
|
|
|
|
{
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
ULONG Polarity;
|
|
VIDEO_X86_BIOS_ARGUMENTS biosArguments;
|
|
VP_STATUS status;
|
|
P2_DECL;
|
|
|
|
DEBUG_PRINT((2, "Permedia2SetPowerState: hwId(%xh) state = %d\n",
|
|
(int)HwId, (int)VideoPowerControl->PowerState));
|
|
|
|
switch((int)HwId)
|
|
{
|
|
|
|
case P2_DDC_MONITOR:
|
|
case P2_NONDDC_MONITOR:
|
|
|
|
Polarity = VideoPortReadRegisterUlong(VIDEO_CONTROL);
|
|
|
|
Polarity &= ~((1 << 5) | (1 << 3) | 1);
|
|
|
|
switch (VideoPowerControl->PowerState)
|
|
{
|
|
|
|
case VideoPowerHibernate:
|
|
case VideoPowerShutdown:
|
|
|
|
//
|
|
// Do nothing for hibernate as the monitor must stay on.
|
|
//
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerOn:
|
|
|
|
RestoreDeviceState(hwDeviceExtension);
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerStandBy:
|
|
|
|
//
|
|
// hsync low, vsync active high, video disabled
|
|
//
|
|
|
|
SaveDeviceState(hwDeviceExtension);
|
|
VideoPortWriteRegisterUlong(VIDEO_CONTROL,
|
|
Polarity | (1 << 5) | (2 << 3) | 0);
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerSuspend:
|
|
|
|
//
|
|
// vsync low, hsync active high, video disabled
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong(VIDEO_CONTROL,
|
|
Polarity | (2 << 5) | (1 << 3) | 0);
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerOff:
|
|
|
|
//
|
|
// vsync low, hsync low, video disabled
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong(VIDEO_CONTROL,
|
|
Polarity | (2 << 5) | (2 << 3) | 0);
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
default:
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetPowerState: Unknown monitor PowerState(%xh)\n",
|
|
(int)VideoPowerControl->PowerState));
|
|
|
|
ASSERT(FALSE);
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Track the current monitor power state
|
|
//
|
|
|
|
hwDeviceExtension->bMonitorPoweredOn =
|
|
(VideoPowerControl->PowerState == VideoPowerOn) ||
|
|
(VideoPowerControl->PowerState == VideoPowerHibernate);
|
|
|
|
Polarity = VideoPortReadRegisterUlong(VIDEO_CONTROL);
|
|
|
|
break;
|
|
|
|
case DISPLAY_ADAPTER_HW_ID:
|
|
|
|
switch (VideoPowerControl->PowerState)
|
|
{
|
|
case VideoPowerHibernate:
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerShutdown:
|
|
|
|
//
|
|
// We need to make sure no interrupts will be generated
|
|
// after the device being powered down
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong(INT_ENABLE, 0);
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerOn:
|
|
|
|
if ((hwDeviceExtension->PreviousPowerState == VideoPowerOff) ||
|
|
(hwDeviceExtension->PreviousPowerState == VideoPowerSuspend) ||
|
|
(hwDeviceExtension->PreviousPowerState == VideoPowerHibernate))
|
|
{
|
|
PowerOnReset(hwDeviceExtension);
|
|
}
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerStandBy:
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerSuspend:
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerOff:
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
default:
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetPowerState: Unknown adapter PowerState(%xh)\n",
|
|
(int)VideoPowerControl->PowerState));
|
|
|
|
ASSERT(FALSE);
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
hwDeviceExtension->PreviousPowerState =
|
|
VideoPowerControl->PowerState;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DEBUG_PRINT((1, "Permedia2SetPowerState: Unknown hwId(%xh)\n",
|
|
(int)HwId));
|
|
|
|
ASSERT(FALSE);
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return(status);
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN PowerOnReset(
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when the adapter is powered on
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
ULONG ulValue;
|
|
BOOLEAN bOK;
|
|
P2_DECL;
|
|
|
|
if(!hwDeviceExtension->bVGAEnabled ||
|
|
!hwDeviceExtension->bDMAEnabled)
|
|
{
|
|
PCI_COMMON_CONFIG PciData;
|
|
|
|
//
|
|
// in a multi-adapter system we'll need to turn on the DMA and
|
|
// memory space for the secondary adapters
|
|
//
|
|
|
|
DEBUG_PRINT((1, "PowerOnReset() enabling memory space access for the secondary card\n"));
|
|
|
|
VideoPortGetBusData( hwDeviceExtension,
|
|
PCIConfiguration,
|
|
0,
|
|
&PciData,
|
|
0,
|
|
PCI_COMMON_HDR_LENGTH);
|
|
|
|
PciData.Command |= PCI_ENABLE_MEMORY_SPACE;
|
|
PciData.Command |= PCI_ENABLE_BUS_MASTER;
|
|
|
|
VideoPortSetBusData( hwDeviceExtension,
|
|
PCIConfiguration,
|
|
0,
|
|
&PciData,
|
|
0,
|
|
PCI_COMMON_HDR_LENGTH );
|
|
|
|
#if DBG
|
|
DumpPCIConfigSpace(hwDeviceExtension, hwDeviceExtension->pciBus,
|
|
(ULONG)hwDeviceExtension->pciSlot.u.AsULONG);
|
|
#endif
|
|
|
|
}
|
|
|
|
//
|
|
// While waking up from hibernation, we usually don't need
|
|
// to reset perm2 and call ProcessInitializationTable()
|
|
// for the primary card since video bios will get posted.
|
|
// We do so here because we saw cases that the perm2 bios
|
|
// failed to worked correctly on some machines.
|
|
//
|
|
|
|
//
|
|
// reset the device
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong(RESET_STATUS, 0);
|
|
|
|
for(i = 0; i < 100000; ++i)
|
|
{
|
|
ulValue = VideoPortReadRegisterUlong(RESET_STATUS);
|
|
|
|
if (ulValue == 0)
|
|
break;
|
|
}
|
|
|
|
if(ulValue)
|
|
{
|
|
DEBUG_PRINT((1, "PowerOnReset() Read RESET_STATUS(%xh) - failed to reset\n",
|
|
ulValue));
|
|
|
|
ASSERT(FALSE);
|
|
bOK = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// reload registers given in ROM
|
|
//
|
|
|
|
if(hwDeviceExtension->culTableEntries)
|
|
{
|
|
ProcessInitializationTable(hwDeviceExtension);
|
|
}
|
|
|
|
//
|
|
// set-up other registers not set in InitializeVideo
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong(BYPASS_WRITE_MASK, 0xFFFFFFFF);
|
|
VideoPortWriteRegisterUlong(APERTURE_ONE, 0x0);
|
|
VideoPortWriteRegisterUlong(APERTURE_TWO, 0x0);
|
|
|
|
bOK = TRUE;
|
|
|
|
}
|
|
|
|
return(bOK);
|
|
|
|
}
|
|
|
|
|
|
VOID SaveDeviceState(PHW_DEVICE_EXTENSION hwDeviceExtension)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Save any registers that will be destroyed when we power down the monitor
|
|
|
|
--*/
|
|
|
|
{
|
|
P2_DECL;
|
|
|
|
DEBUG_PRINT((2, "SaveDeviceState() called\n"));
|
|
|
|
//
|
|
// hwDeviceExtension->VideoControl should be set in InitializeVideo,
|
|
// just in case we get here before InitializeVideo
|
|
//
|
|
|
|
if( !(hwDeviceExtension->VideoControl) )
|
|
{
|
|
hwDeviceExtension->VideoControl =
|
|
VideoPortReadRegisterUlong(VIDEO_CONTROL);
|
|
}
|
|
|
|
hwDeviceExtension->IntEnable = VideoPortReadRegisterUlong(INT_ENABLE);
|
|
|
|
}
|
|
|
|
|
|
VOID RestoreDeviceState(PHW_DEVICE_EXTENSION hwDeviceExtension)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Restore registers saved before monitor power down
|
|
|
|
--*/
|
|
|
|
{
|
|
P2_DECL;
|
|
|
|
DEBUG_PRINT((2, "RestoreDeviceState() called\n"));
|
|
VideoPortWriteRegisterUlong(VIDEO_CONTROL, hwDeviceExtension->VideoControl);
|
|
VideoPortWriteRegisterUlong(INT_ENABLE, hwDeviceExtension->IntEnable);
|
|
|
|
}
|
|
|
|
|
|
ULONG
|
|
Permedia2GetChildDescriptor(
|
|
PVOID HwDeviceExtension,
|
|
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
|
|
PVIDEO_CHILD_TYPE pChildType,
|
|
PVOID pChildDescriptor,
|
|
PULONG pUId,
|
|
PULONG pUnused )
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate all child devices controlled by the Permedia 2 chip.
|
|
|
|
This includes DDC monitors attached to the board, as well as other devices
|
|
which may be connected to a proprietary bus.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension -
|
|
Pointer to our hardware device extension structure.
|
|
|
|
ChildEnumInfo -
|
|
Information about the device that should be enumerated.
|
|
|
|
pChildType -
|
|
Type of child we are enumerating - monitor, I2C ...
|
|
|
|
pChildDescriptor -
|
|
Identification structure of the device (EDID, string)
|
|
|
|
pUId -
|
|
Private unique 32 bit ID to passed back to the miniport
|
|
|
|
pUnused -
|
|
Do not use
|
|
|
|
Return Value:
|
|
|
|
ERROR_NO_MORE_DEVICES -
|
|
if no more child devices exist.
|
|
|
|
ERROR_INVALID_NAME -
|
|
The miniport could not enumerate the child device identified in
|
|
ChildEnumInfo but does have more devices to be enumerated.
|
|
|
|
ERROR_MORE_DATA -
|
|
There are more devices to be enumerated.
|
|
|
|
Note:
|
|
|
|
In the event of a failure return, none of the fields are valid except for
|
|
the return value and the pMoreChildren field.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetChildDescriptor called\n"));
|
|
|
|
switch (ChildEnumInfo->ChildIndex)
|
|
{
|
|
case 0:
|
|
|
|
//
|
|
// Case 0 is used to enumerate devices found by the ACPI firmware.
|
|
// We do not currently support ACPI devices
|
|
//
|
|
|
|
return ERROR_NO_MORE_DEVICES;
|
|
|
|
case 1:
|
|
|
|
//
|
|
// Treat index 1 as the monitor
|
|
//
|
|
|
|
*pChildType = Monitor;
|
|
|
|
//
|
|
// if it's a DDC monitor we return its EDID in pjBuffer
|
|
// (always 128 bytes)
|
|
//
|
|
|
|
if(VideoPortDDCMonitorHelper(HwDeviceExtension,
|
|
&I2CFunctionTable,
|
|
pChildDescriptor,
|
|
ChildEnumInfo->ChildDescriptorSize))
|
|
{
|
|
//
|
|
// found a DDC monitor
|
|
//
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetChildDescriptor: found a DDC monitor\n"));
|
|
|
|
*pUId = P2_DDC_MONITOR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// failed: assume non-DDC monitor
|
|
//
|
|
|
|
DEBUG_PRINT((2, "Permedia2GetChildDescriptor: found a non-DDC monitor\n"));
|
|
|
|
*pUId = P2_NONDDC_MONITOR;
|
|
|
|
}
|
|
|
|
return ERROR_MORE_DATA;
|
|
|
|
default:
|
|
|
|
return ERROR_NO_MORE_DEVICES;
|
|
}
|
|
}
|
|
|
|
|
|
VOID I2CWriteClock(PVOID HwDeviceExtension, UCHAR data)
|
|
{
|
|
const ULONG nbitClock = 3;
|
|
const ULONG Clock = 1 << nbitClock;
|
|
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
ULONG ul;
|
|
P2_DECL;
|
|
|
|
ul = VideoPortReadRegisterUlong(DDC_DATA);
|
|
ul &= ~Clock;
|
|
ul |= (data & 1) << nbitClock;
|
|
VideoPortWriteRegisterUlong(DDC_DATA, ul);
|
|
}
|
|
|
|
VOID I2CWriteData(PVOID HwDeviceExtension, UCHAR data)
|
|
{
|
|
const ULONG nbitData = 2;
|
|
const ULONG Data = 1 << nbitData;
|
|
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
ULONG ul;
|
|
P2_DECL;
|
|
|
|
ul = VideoPortReadRegisterUlong(DDC_DATA);
|
|
ul &= ~Data;
|
|
ul |= ((data & 1) << nbitData);
|
|
VideoPortWriteRegisterUlong(DDC_DATA, ul);
|
|
}
|
|
|
|
BOOLEAN I2CReadClock(PVOID HwDeviceExtension)
|
|
{
|
|
const ULONG nbitClock = 1;
|
|
const ULONG Clock = 1 << nbitClock;
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
ULONG ul;
|
|
P2_DECL;
|
|
|
|
ul = VideoPortReadRegisterUlong(DDC_DATA);
|
|
ul &= Clock;
|
|
ul >>= nbitClock;
|
|
|
|
return((BOOLEAN)ul);
|
|
}
|
|
|
|
BOOLEAN I2CReadData(PVOID HwDeviceExtension)
|
|
{
|
|
const ULONG nbitData = 0;
|
|
const ULONG Data = 1 << nbitData;
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
ULONG ul;
|
|
P2_DECL;
|
|
|
|
ul = VideoPortReadRegisterUlong(DDC_DATA);
|
|
ul &= Data;
|
|
ul >>= nbitData;
|
|
return((BOOLEAN)ul);
|
|
}
|
|
|
|
VOID I2CWaitVSync(PVOID HwDeviceExtension)
|
|
{
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
UCHAR jIndexSaved, jStatus;
|
|
P2_DECL;
|
|
|
|
if(hwDeviceExtension->bVGAEnabled)
|
|
{
|
|
|
|
//
|
|
// VGA run on this board, is it currently in VGA or VTG mode?
|
|
//
|
|
|
|
jIndexSaved = VideoPortReadRegisterUchar(PERMEDIA_MMVGA_INDEX_REG);
|
|
|
|
VideoPortWriteRegisterUchar(PERMEDIA_MMVGA_INDEX_REG,
|
|
PERMEDIA_VGA_CTRL_INDEX);
|
|
|
|
jStatus = VideoPortReadRegisterUchar(PERMEDIA_MMVGA_DATA_REG);
|
|
|
|
VideoPortWriteRegisterUchar(PERMEDIA_MMVGA_INDEX_REG, jIndexSaved);
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// VGA not run
|
|
//
|
|
|
|
jStatus = 0;
|
|
|
|
}
|
|
|
|
|
|
if(jStatus & PERMEDIA_VGA_ENABLE)
|
|
{
|
|
//
|
|
// in VGA, so check VSync via the VGA registers
|
|
// 1. if we're in VSync, wait for it to end
|
|
//
|
|
|
|
while( (VideoPortReadRegisterUchar(PERMEDIA_MMVGA_STAT_REG) &
|
|
PERMEDIA_VGA_STAT_VSYNC) == 1);
|
|
|
|
//
|
|
// 2. wait for the start of VSync
|
|
//
|
|
|
|
while( (VideoPortReadRegisterUchar(PERMEDIA_MMVGA_STAT_REG) &
|
|
PERMEDIA_VGA_STAT_VSYNC) == 0);
|
|
}
|
|
else
|
|
{
|
|
if(!hwDeviceExtension->bVTGRunning)
|
|
{
|
|
|
|
//
|
|
// time to set-up the VTG - we'll need a valid mode to do this,
|
|
// so we;ll choose 640x480x8 we get here (at boot-up only) if
|
|
// the secondary card has VGA disabled: GetChildDescriptor is
|
|
// called before InitializeVideo so that the VTG hasn't been
|
|
// programmed yet
|
|
//
|
|
|
|
DEBUG_PRINT((2, "I2CWaitVSync() - VGA nor VTG running: attempting to setup VTG\n"));
|
|
|
|
if(hwDeviceExtension->pFrequencyDefault == NULL)
|
|
{
|
|
DEBUG_PRINT((1, "I2CWaitVSync() - no valid modes to use: can't set-up VTG\n"));
|
|
return;
|
|
}
|
|
|
|
Permedia2GetClockSpeeds(HwDeviceExtension);
|
|
ZeroMemAndDac(hwDeviceExtension, 0);
|
|
|
|
if (!InitializeVideo( HwDeviceExtension,
|
|
hwDeviceExtension->pFrequencyDefault) )
|
|
{
|
|
DEBUG_PRINT((1, "I2CWaitVSync() - InitializeVideo failed\n"));
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// VTG has been set-up: check via the control registers
|
|
//
|
|
|
|
VideoPortWriteRegisterUlong ( INT_FLAGS,
|
|
INTR_VBLANK_SET );
|
|
|
|
while (( (VideoPortReadRegisterUlong (INT_FLAGS) ) &
|
|
INTR_VBLANK_SET ) == 0 );
|
|
}
|
|
}
|