windows-nt/Source/XPSP1/NT/drivers/video/ms/weitek/mini/p9.c
2020-09-26 16:20:57 +08:00

2651 lines
69 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1993 Weitek Corporation
Module Name:
p9.c
Abstract:
This module contains the code that implements the Weitek P9 miniport
device driver.
Environment:
Kernel mode
Revision History may be found at the end of this file.
--*/
#include "p9.h"
#include "p9gbl.h"
#include "vga.h"
#include "string.h"
#include "p91regs.h"
#include "p9errlog.h"
//
// This global is used as an error flag to error out quickly on the multiple
// calls to P9FindAdapter when a board is not supported.
//
extern VP_STATUS vpP91AdapterStatus;
extern BOOLEAN bFoundPCI;
extern ULONG P91_Bt485_DAC_Regs[];
BOOLEAN gMadeAdjustments=FALSE;
extern BOOLEAN
bIntergraphBoard(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
extern VOID SetVgaMode3(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
extern VOID
WriteP9ConfigRegister(
PHW_DEVICE_EXTENSION HwDeviceExtension,
UCHAR regnum,
UCHAR jValue
);
extern VOID
InitP9100(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
extern VOID
P91_SysConf(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
extern VOID
P91_WriteTiming(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
extern VOID vDumpPCIConfig(PHW_DEVICE_EXTENSION HwDeviceExtension,
PUCHAR psz);
extern
VOID
P91RestoreVGAregs(
PHW_DEVICE_EXTENSION HwDeviceExtension,
VGA_REGS * SaveVGARegisters);
extern
VOID
P91SaveVGARegs(
PHW_DEVICE_EXTENSION HwDeviceExtension,
VGA_REGS * SaveVGARegisters);
//
// Local function Prototypes
//
// Functions that start with 'P9' are entry points for the OS port driver.
//
VP_STATUS
GetCPUIdCallback(
PVOID HwDeviceExtension,
PVOID Context,
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
PVOID Identifier,
ULONG IdentifierLength,
PVOID ConfigurationData,
ULONG ConfigurationDataLength,
PVOID ComponentInformation,
ULONG ComponentInformationLength
);
VP_STATUS
GetDeviceDataCallback(
PVOID HwDeviceExtension,
PVOID Context,
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
PVOID Identifier,
ULONG IdentifierLength,
PVOID ConfigurationData,
ULONG ConfigurationDataLength,
PVOID ComponentInformation,
ULONG ComponentInformationLength
);
VOID
DevSetRegistryParams(
PHW_DEVICE_EXTENSION hwDeviceExtension
);
VP_STATUS
FindAdapter(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVOID HwContext,
PWSTR ArgumentString,
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
PP9ADAPTER pCurAdapter
);
VP_STATUS
P9FindAdapter(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVOID HwContext,
PWSTR ArgumentString,
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
PUCHAR Again
);
BOOLEAN
P9Initialize(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN
P9StartIO(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVIDEO_REQUEST_PACKET RequestPacket
);
VOID
DevInitP9(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VOID
DevDisableP9(
PHW_DEVICE_EXTENSION HwDeviceExtension,
BOOLEAN BugCheck
);
VP_STATUS
P9QueryNamedValueCallback(
PVOID HwDeviceExtension,
PVOID Context,
PWSTR ValueName,
PVOID ValueData,
ULONG ValueLength
);
BOOLEAN
P9ResetVideo(
IN PVOID HwDeviceExtension,
IN ULONG Columns,
IN ULONG Rows
);
VOID
InitializeModes(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
//
// New entry points added for NT 5.0.
//
#if (_WIN32_WINNT >= 500)
//
// Routine to set a desired DPMS power management state.
//
VP_STATUS
WP9SetPower50(
PHW_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
);
//
// Routine to retrieve possible DPMS power management states.
//
VP_STATUS
WP9GetPower50(
PHW_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
);
//
// Routine to retrieve the Enhanced Display ID structure via DDC
//
ULONG
WP9GetVideoChildDescriptor(
PVOID HwDeviceExtension,
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
PVIDEO_CHILD_TYPE pChildType,
PVOID pvChildDescriptor,
PULONG pHwId,
PULONG pUnused
);
#endif // _WIN32_WINNT >= 500
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE,DriverEntry)
#pragma alloc_text(PAGE,GetCPUIdCallback)
#pragma alloc_text(PAGE,GetDeviceDataCallback)
#pragma alloc_text(PAGE,DevSetRegistryParams)
#pragma alloc_text(PAGE,P9FindAdapter)
#pragma alloc_text(PAGE,FindAdapter)
#pragma alloc_text(PAGE,P9Initialize)
#pragma alloc_text(PAGE,P9StartIO)
#if (_WIN32_WINNT >= 500)
#pragma alloc_text(PAGE_COM, WP9SetPower50)
#pragma alloc_text(PAGE_COM, WP9GetPower50)
#pragma alloc_text(PAGE_COM, WP9GetVideoChildDescriptor)
#endif // _WIN32_WINNT >= 500
/*****************************************************************************
*
* IMPORTANT:
*
* Some routines, like DevDisable, can not be paged since they are called
* when the system is bugchecking
*
****************************************************************************/
// #pragma alloc_text(PAGE, DevDisableP9)
#endif
ULONG
DriverEntry (
PVOID Context1,
PVOID Context2
)
/*++
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
Context1 - First context value passed by the operating system. This is
the value with which the miniport driver calls VideoPortInitialize().
Context2 - Second context value passed by the operating system. This is
the value with which the miniport driver calls VideoPortInitialize().
Return Value:
Status from VideoPortInitialize()
--*/
{
VIDEO_HW_INITIALIZATION_DATA hwInitData;
ULONG status = ERROR_DEV_NOT_EXIST;
VideoDebugPrint((2, "DriverEntry ----------\n"));
//
// Zero out structure.
//
VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
//
// Specify sizes of structure and extension.
//
hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
//
// Set entry points.
//
hwInitData.HwFindAdapter = P9FindAdapter;
hwInitData.HwInitialize = P9Initialize;
hwInitData.HwInterrupt = NULL;
hwInitData.HwStartIO = P9StartIO;
hwInitData.HwResetHw = P9ResetVideo;
#if (_WIN32_WINNT >= 500)
//
// Set new entry points added for NT 5.0.
//
hwInitData.HwSetPowerState = WP9SetPower50;
hwInitData.HwGetPowerState = WP9GetPower50;
hwInitData.HwGetVideoChildDescriptor = WP9GetVideoChildDescriptor;
#endif // _WIN32_WINNT >= 500
//
// Determine the size we require for the device extension.
//
//
// Compute the size of the device extension by adding in the
// number of DAC Registers.
//
hwInitData.HwDeviceExtensionSize =
sizeof(HW_DEVICE_EXTENSION) +
(17) * sizeof(PVOID);
//
// This driver accesses one range of memory one range of control
// register and a last range for cursor control.
//
// hwInitData.NumberOfAccessRanges = 0;
//
// There is no support for the V86 emulator in this driver so this field
// is ignored.
//
// hwInitData.NumEmulatorAccessEntries = 0;
//
// This device supports many bus types.
//
// SNI has implemented machines with both VL and PCI versions of the
// weitek chipset. Don't bother with the other buses since the
// detection code may actually crash some MIPS boxes.
//
hwInitData.AdapterInterfaceType = PCIBus;
status = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
if (status == NO_ERROR)
{
VideoDebugPrint((2, "DriverEntry SUCCESS for PCI\n"));
bFoundPCI = TRUE;
return(status);
}
//
// As of NT5, we won't support weitek PCI with any other weitek on
// the same machine.
//
if (bFoundPCI)
return ERROR_DEV_NOT_EXIST;
hwInitData.AdapterInterfaceType = Isa;
status = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
if ((status == NO_ERROR))
{
VideoDebugPrint((2, "DriverEntry SUCCESS for ISA\n"));
return(status);
}
hwInitData.AdapterInterfaceType = Eisa;
status = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
if ((status == NO_ERROR))
{
VideoDebugPrint((2, "DriverEntry SUCCESS for EISA\n"));
return(status);
}
hwInitData.AdapterInterfaceType = Internal;
status = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
if ((status == NO_ERROR))
{
VideoDebugPrint((2, "DriverEntry SUCCESS at for Internal\n"));
return(status);
}
return(status);
} // end DriverEntry()
VP_STATUS
P9FindAdapter (
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVOID HwContext,
PWSTR ArgumentString,
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
PUCHAR Again
)
/*++
Routine Description:
Arguments:
Return Value:
Status from FindAdapter()
--*/
{
ULONG status;
UCHAR i;
*Again = TRUE;
VideoDebugPrint((2, "P9FindAdapter entry\n"));
//
// Loop through the table of types of cards. DriverEntry() loops through
// the bus types.
//
for (i = 0; i < NUM_OEM_ADAPTERS; i++)
{
VideoDebugPrint((2, "Loop %d in P9FindAdapter\n", i));
status = FindAdapter(HwDeviceExtension,
HwContext,
ArgumentString,
ConfigInfo,
&(OEMAdapter[i]));
if (status == NO_ERROR)
{
VideoDebugPrint((2, "P9FindAdapter SUCCESS at loop %d\n", i));
//
// Indicate we do not wish to be called over
//
*Again = FALSE;
break;
}
}
//
// If we've exhausted the table, request to not be recalled.
//
if ( i == NUM_OEM_ADAPTERS)
{
VideoDebugPrint((1, "P9FindAdapter FAILED\n", i));
*Again = FALSE;
}
return(status);
} // end P9FindAdapter()
VP_STATUS
pVlCardDetect(
PVOID HwDeviceExtension,
PVOID Context,
PWSTR ValueName,
PVOID ValueData,
ULONG ValueLength
)
/*++
Routine Description:
This routine determines if the driver is the ForceVga.
Arguments:
Return Value:
return STATUS_SUCCESS if we are in DEADMAN_KEY state
return failiure otherwise.
--*/
{
#ifdef _X86_
if (ValueData &&
ValueLength &&
(*((PULONG)ValueData) == 1)) {
VideoDebugPrint((2, "doing VL card detection\n"));
return NO_ERROR;
} else {
return ERROR_INVALID_PARAMETER;
}
#else
//
// we never have a VL bus on non-x86 systems
//
return ERROR_INVALID_PARAMETER;
#endif
}
VP_STATUS
GetCPUIdCallback(
PVOID HwDeviceExtension,
PVOID Context,
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
PVOID Identifier,
ULONG IdentifierLength,
PVOID ConfigurationData,
ULONG ConfigurationDataLength,
PVOID ComponentInformation,
ULONG ComponentInformationLength
)
{
VideoDebugPrint((2, "Weitek: Check the SNI CPU ID\n"));
//
// We do not want to try to detect the weitekp9 if there isn't one present.
// (Kind of a paradox?)
//
if (Identifier) {
if (VideoPortCompareMemory(Context,
Identifier,
IdentifierLength) == IdentifierLength)
{
return NO_ERROR;
}
}
return ERROR_DEV_NOT_EXIST;
} //end GetCPUIdCallback()
VP_STATUS
GetDeviceDataCallback(
PVOID HwDeviceExtension,
PVOID Context,
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
PVOID Identifier,
ULONG IdentifierLength,
PVOID ConfigurationData,
ULONG ConfigurationDataLength,
PVOID ComponentInformation,
ULONG ComponentInformationLength
)
{
PVIDEO_HARDWARE_CONFIGURATION_DATA configData = ConfigurationData;
PHW_DEVICE_EXTENSION hwDeviceExtension;
ULONG i;
hwDeviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
VideoDebugPrint((2, "Weitek: controller information is present\n"));
//
// We do not want to try to detect the weitekp9 if there isn't one present.
// (Kind of a paradox?)
//
if (Identifier) {
if (VideoPortCompareMemory(L"DIAMOND P9000 VLBUS",
Identifier,
sizeof(L"DIAMOND P9000 VLBUS")) ==
sizeof(L"DIAMOND P9000 VLBUS"))
{
hwDeviceExtension->MachineType = SIEMENS;
}
else if (VideoPortCompareMemory(L"DIAMOND P9100 VLBUS",
Identifier,
sizeof(L"DIAMOND P9100 VLBUS")) ==
sizeof(L"DIAMOND P9100 VLBUS"))
{
hwDeviceExtension->MachineType = SIEMENS_P9100_VLB;
}
else
{
return ERROR_DEV_NOT_EXIST;
}
VideoDebugPrint((1, "Siemens Nixdorf RM400 VL with Weitek P9%d00\n",
hwDeviceExtension->MachineType == SIEMENS ? 0:1));
hwDeviceExtension->P9PhysAddr.LowPart = 0x1D000000;
//
// adjust DriverAccessRanges for Siemens box
//
// This routine may be called several times, but we
// only want to do this once!
//
if (!gMadeAdjustments)
{
ULONG adjust;
if ((hwDeviceExtension->MachineType == SIEMENS_P9100_VLB) &&
(VideoPortIsCpu(L"RM400-MT") || VideoPortIsCpu(L"RM400-T")
||VideoPortIsCpu(L"RM400-T MP")))
{
//
// If we have a P9100 VLB and it's *not* on a RM200
// then use the new address.
//
// Otherwise, use the old address.
//
adjust = 0x1E000000;
}
else if (hwDeviceExtension->MachineType == SIEMENS
|| VideoPortIsCpu(L"RM200"))
{
adjust = 0x14000000;
}
else return ERROR_DEV_NOT_EXIST;
DriverAccessRanges[1].RangeStart.LowPart += adjust;
for(i=0; i<0x10; i++)
{
VLDefDACRegRange[i].RangeStart.LowPart += adjust;
}
gMadeAdjustments = TRUE;
}
}
return NO_ERROR;
} //end GetDeviceDataCallback()
VP_STATUS
P9QueryNamedValueCallback(
PVOID HwDeviceExtension,
PVOID Context,
PWSTR ValueName,
PVOID ValueData,
ULONG ValueLength
)
{
if (ValueLength == 4)
{
*((PULONG) Context) = *((PULONG)ValueData);
return(NO_ERROR);
}
else
{
return(ERROR_INVALID_PARAMETER);
}
}
VOID
WeitekP91NapTime(
VOID
)
{
ULONG count;
for (count=0; count<100; count) {
VideoPortStallExecution(1000);
++count;
}
}
VP_STATUS
FindAdapter(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVOID HwContext,
PWSTR ArgumentString,
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
PP9ADAPTER pCurAdapter
)
/*++
Routine Description:
This routine is called to determine if the adapter for this driver
is present in the system.
If it is present, the function fills out some information describing
the adapter.
Arguments:
HwDeviceExtension - Supplies the miniport driver's adapter storage. This
storage is initialized to zero before this call.
HwContext - Supplies the context value which was passed to
VideoPortInitialize(). Must be NULL for PnP drivers.
ArgumentString - Suuplies a NULL terminated ASCII string. This string
originates from the user.
ConfigInfo - Returns the configuration information structure which is
filled by the miniport driver. This structure is initialized with
any knwon configuration information (such as SystemIoBusNumber) by
the port driver. Where possible, drivers should have one set of
defaults which do not require any supplied configuration information.
Again - Indicates if the miniport driver wants the port driver to call
its VIDEO_HW_FIND_ADAPTER function again with a new
and the same config info. This is used by the miniport drivers which
can search for several adapters on a bus.
NO_ERROR - Indicates a host adapter was found and the
configuration information was successfully determined.
ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
error obtaining the configuration information. If possible an error
should be logged.
ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
supplied configuration information.
--*/
{
PULONG pVirtAddr;
SHORT i;
ULONG TotalRanges;
ULONG CoProcId;
VP_STATUS vpCurrStatus = NO_ERROR;
VGA_REGS VGAregs;
BOOLEAN bRetryP9100 = TRUE;
VideoDebugPrint((2, "FindAdapter: enter\n"));
//
// NOTE:
// Important workaround for detection:
//
// We can not always autodetect Weitek VL designs because many machines
// will NMI if we try to access the high memory locations at which the
// card is present.
//
// We will only "detect" the Weitek VL cards if the user specifically
// installed the weitek driver using the video applet.
//
// We will only autodetect the PCI and Viper VL designs. The bAutoDetect
// field in the adapter info structure indicates if a design can be
// autodetected.
//
if ((!pCurAdapter->pAdapterDesc->bAutoDetect) &&
!bFoundPCI &&
VideoPortGetRegistryParameters(HwDeviceExtension,
L"DetectVLCards",
FALSE,
pVlCardDetect,
NULL) != NO_ERROR)
{
VideoDebugPrint((1, "FindAdapter: failed to autodetect\n"));
return(ERROR_DEV_NOT_EXIST);
}
//
// If the bus type in pCurAdapter->pAdapterDesc is PCI, but
// the AdapterInterfaceType in ConfigInfo is not PCI, return
// ERROR_DEV_NOT_EXIST.
//
if ((ConfigInfo->AdapterInterfaceType == PCIBus) &&
(!pCurAdapter->pAdapterDesc->bPCIAdapter))
return ERROR_DEV_NOT_EXIST;
HwDeviceExtension->P9PhysAddr.HighPart = 0;
HwDeviceExtension->P9PhysAddr.LowPart = 0;
VideoPortGetRegistryParameters((PVOID) HwDeviceExtension,
L"Membase",
FALSE,
P9QueryNamedValueCallback,
(PVOID) &(HwDeviceExtension->P9PhysAddr.LowPart));
// SNI is shipping MIPS machine with Internal and PCI versions of the
// weitek chips. For other buses, don't try to load
// For MIPS machine with an Internal Bus, check the ID
// for PPC, we just go through normal detection
//
#if defined(_MIPS_)
if (ConfigInfo->AdapterInterfaceType == Internal)
{
//
// Let get the hardware information from the hardware description
// part of the registry.
//
// Check if there is a video adapter on the internal bus.
// Exit right away if there is not.
//
if (NO_ERROR != VideoPortGetDeviceData(HwDeviceExtension,
VpControllerData,
&GetDeviceDataCallback,
pCurAdapter))
{
VideoDebugPrint((1, "Weitek: VideoPort get controller info failed\n"));
return ERROR_INVALID_PARAMETER;
}
}
else if(ConfigInfo->AdapterInterfaceType != PCIBus)
return ERROR_INVALID_PARAMETER;
#endif
//
// Move the various Hw component structures for this board into the
// device extension.
//
VideoPortMoveMemory(&HwDeviceExtension->P9CoprocInfo,
pCurAdapter->pCoprocInfo,
sizeof(P9_COPROC));
VideoPortMoveMemory(&HwDeviceExtension->AdapterDesc,
pCurAdapter->pAdapterDesc,
sizeof(ADAPTER_DESC));
VideoPortMoveMemory(&HwDeviceExtension->Dac,
pCurAdapter->pDac,
sizeof(DAC));
//
// Set up the array of register ptrs in the device extension:
// the OEMGetBaseAddr routine will need them if a board is found.
// The arrays are kept at the very end of the device extension and
// are order dependent.
//
(PUCHAR) HwDeviceExtension->pDACRegs = (PUCHAR) HwDeviceExtension +
sizeof(HW_DEVICE_EXTENSION);
//
// Call the OEMGetBaseAddr routine to determine if the board is
// installed.
//
VideoDebugPrint((2, "AdapterInterfaceType:%d\n", ConfigInfo->AdapterInterfaceType));
if (!pCurAdapter->pAdapterDesc->OEMGetBaseAddr(HwDeviceExtension))
{
VideoDebugPrint((1, "FindAdapter, GetBaseAddr Failed, line %d\n", __LINE__));
return(ERROR_DEV_NOT_EXIST);
}
//
// We found an adapter, pickup a local for the chip type.
//
CoProcId = pCurAdapter->pCoprocInfo->CoprocId;
//
// Make sure the size of the structure is at least as large as what we
// are expecting (check version of the config info structure).
//
if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO))
{
VideoDebugPrint((1, "FindAdapter Failed, wrong version, line %d\n", __LINE__));
return ERROR_INVALID_PARAMETER;
}
//
// Clear out the Emulator entries and the state size since this driver
// does not support them.
//
ConfigInfo->NumEmulatorAccessEntries = 0;
ConfigInfo->EmulatorAccessEntries = NULL;
ConfigInfo->EmulatorAccessEntriesContext = 0;
ConfigInfo->HardwareStateSize = 0;
if ((CoProcId == P9000_ID) && !(pCurAdapter->pAdapterDesc->bPCIAdapter))
{
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0L;
ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0L;
ConfigInfo->VdmPhysicalVideoMemoryLength = 0L;
}
else
{
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = MEM_VGA_ADDR;
ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0L;
ConfigInfo->VdmPhysicalVideoMemoryLength = MEM_VGA_SIZE;
if(HwDeviceExtension->MachineType == SIEMENS_P9100_PCi)
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart |= 0x10000000;
}
//
// The OEMGetBaseAddr routine should have initialized the following
// data structures:
//
// 1) The DAC access ranges in DriverAccessRanges.
// 2) The P9PhysAddr field in the device extension.
//
//
// Initialize the physical address for the registers and frame buffer.
//
HwDeviceExtension->CoprocPhyAddr = HwDeviceExtension->P9PhysAddr;
HwDeviceExtension->CoprocPhyAddr.LowPart +=
HwDeviceExtension->P9CoprocInfo.CoprocRegOffset;
HwDeviceExtension->PhysicalFrameAddr = HwDeviceExtension->P9PhysAddr;
HwDeviceExtension->PhysicalFrameAddr.LowPart +=
HwDeviceExtension->P9CoprocInfo.FrameBufOffset;
//
// Initialize the access range structure with the base address values
// so the driver can register its memory usage.
//
DriverAccessRanges[0].RangeStart =
HwDeviceExtension->P9PhysAddr;
DriverAccessRanges[0].RangeLength =
HwDeviceExtension->P9CoprocInfo.AddrSpace;
if (CoProcId == P9000_ID)
{
//
// Init the total number of standard access ranges.
//
TotalRanges = NUM_DRIVER_ACCESS_RANGES + NUM_DAC_ACCESS_RANGES + 1;
}
else
{
TotalRanges = NUM_DRIVER_ACCESS_RANGES;
}
//
// Check to see if another miniport driver has allocated any of the
// coprocessor's memory space.
//
if (VideoPortVerifyAccessRanges(HwDeviceExtension,
TotalRanges,
DriverAccessRanges) != NO_ERROR)
{
if (HwDeviceExtension->AdapterDesc.bRequiresIORanges)
{
//
// If we need more then just the coproc ranges, and couldn't get
// then we need to fail.
//
VideoDebugPrint((1, "FindAdapter : (ERROR) VideoPortVerifyAccessRanges - Failed 1\n"));
return ERROR_INVALID_PARAMETER;
}
else
{
//
// We couldn't claim all of the access ranges. However, this is a
// card which really only needs the coproc and frame buffer range.
//
if (DriverAccessRanges[0].RangeStart.LowPart &&
VideoPortVerifyAccessRanges(HwDeviceExtension,
1,
DriverAccessRanges) != NO_ERROR)
{
//
// This access range we can't do without
//
VideoDebugPrint((1, "FindAdapter : (ERROR) VideoPortVerifyAccessRanges - Failed 2\n"));
return ERROR_INVALID_PARAMETER;
}
}
}
else
{
//
// If we get here, then we must have successfully claimed
// the VGA access ranges. Lets map them in.
//
HwDeviceExtension->Vga =
VideoPortGetDeviceBase(HwDeviceExtension,
DriverAccessRanges[1].RangeStart,
DriverAccessRanges[1].RangeLength,
DriverAccessRanges[1].RangeInIoSpace);
}
//
// map coproc, frame buffer, and vga ports
//
{
PHYSICAL_ADDRESS Base;
Base = DriverAccessRanges[0].RangeStart;
Base.QuadPart += HwDeviceExtension->P9CoprocInfo.CoprocRegOffset;
HwDeviceExtension->Coproc =
VideoPortGetDeviceBase(HwDeviceExtension,
Base,
0x100000,
DriverAccessRanges[0].RangeInIoSpace);
Base = DriverAccessRanges[0].RangeStart;
Base.QuadPart += HwDeviceExtension->P9CoprocInfo.FrameBufOffset;
HwDeviceExtension->FrameAddress =
VideoPortGetDeviceBase(HwDeviceExtension,
Base,
HwDeviceExtension->P9CoprocInfo.AddrSpace -
HwDeviceExtension->P9CoprocInfo.FrameBufOffset,
DriverAccessRanges[0].RangeInIoSpace);
}
if( HwDeviceExtension->Coproc == NULL ||
HwDeviceExtension->FrameAddress == NULL ||
(HwDeviceExtension->Vga == NULL &&
HwDeviceExtension->AdapterDesc.bRequiresIORanges))
{
VideoDebugPrint((1, "weitekp9: VideoPortGetDeviceBase failed.\n"));
return ERROR_INVALID_PARAMETER;
}
if (CoProcId == P9000_ID)
{
//
// Map all of the DAC registers into system virtual address space.
// These registers are mapped seperately from the coprocessor and DAC
// registers since their virtual addresses must be kept in an array
// at the end of the device extension.
//
for (i = 0; i < NUM_DAC_ACCESS_RANGES; i++)
{
if ( (HwDeviceExtension->pDACRegs[i] =
(ULONG)(ULONG_PTR) VideoPortGetDeviceBase(HwDeviceExtension,
DriverAccessRanges[i + NUM_DRIVER_ACCESS_RANGES].RangeStart,
DriverAccessRanges[i + NUM_DRIVER_ACCESS_RANGES].RangeLength,
DriverAccessRanges[i + NUM_DRIVER_ACCESS_RANGES].RangeInIoSpace)) == 0)
{
return ERROR_INVALID_PARAMETER;
}
}
}
else
{
for (i = 0; i < NUM_DAC_ACCESS_RANGES; i++)
{
HwDeviceExtension->pDACRegs[i] = P91_Bt485_DAC_Regs[i];
}
}
// NOTE: !!! jn 1294
// On the P9100 we will always allocate the a full 12 meg
// of address space...
if (CoProcId == P9000_ID)
{
//
// Enable the video memory so it can be sized.
//
if (HwDeviceExtension->AdapterDesc.P9EnableMem)
{
if (!HwDeviceExtension->AdapterDesc.P9EnableMem(HwDeviceExtension))
{
return(FALSE);
}
}
//
// Determine the amount of video memory installed.
//
HwDeviceExtension->P9CoprocInfo.SizeMem(HwDeviceExtension);
}
//
// Detect the DAC type.
// !!!
// On the X86, This requires switching into native mode, so the screen
// will be dark for the remainder of boot.
//
if (CoProcId == P9100_ID)
{
ULONG ulPuConfig;
/*
** SNI-Od: Save all VGA registers before we switch
** to native mode
*/
VideoDebugPrint((2, "Before save\n"));
P91SaveVGARegs(HwDeviceExtension,&VGAregs);
VideoDebugPrint((2, "After save\n"));
WeitekP91NapTime();
// If we have found a serious error, don't go any further. We have already
// logged the error if the status is set in HwDeviceExtension
if ( vpP91AdapterStatus != NO_ERROR )
{
P91RestoreVGAregs(HwDeviceExtension,&VGAregs);
return (ERROR_DEV_NOT_EXIST);
}
// Get into Native mode
if (HwDeviceExtension->usBusType == VESA)
{
WriteP9ConfigRegister(HwDeviceExtension, P91_CONFIG_CONFIGURATION, 3);
VideoDebugPrint((2, "WroteConfig 1\n"));
}
WriteP9ConfigRegister(HwDeviceExtension, P91_CONFIG_MODE, 0);
VideoDebugPrint((2, "WroteConfig 2\n"));
WeitekP91NapTime();
HwDeviceExtension->p91State.ulPuConfig = P9_RD_REG(P91_PU_CONFIG);
// Look to see if it is an Intergraph board - if so, we want to error out
if ( bIntergraphBoard(HwDeviceExtension) == TRUE )
{
vpCurrStatus = P9_INTERGRAPH_FOUND;
goto error1;
}
// Determine the VRAM type:
HwDeviceExtension->p91State.bVram256 =
(HwDeviceExtension->p91State.ulPuConfig & P91_PUC_MEMORY_DEPTH)
? FALSE : TRUE;
// Size the memory
P91SizeVideoMemory(HwDeviceExtension);
VideoDebugPrint((2, "Sized mem\n"));
WeitekP91NapTime();
// Setup the Hardware Device Extension.
// So the mode counter will work.
HwDeviceExtension->FrameLength = HwDeviceExtension->p91State.ulFrameBufferSize;
// Make sure we are supporting the correct DAC.
ulPuConfig = HwDeviceExtension->p91State.ulPuConfig;
if ((ulPuConfig & P91_PUC_RAMDAC_TYPE) == P91_PUC_DAC_IBM525)
{
if (HwDeviceExtension->Dac.ulDacId != DAC_ID_IBM525)
{
VideoDebugPrint((1, "WEITEKP9! WARNING - Detected an IBM525 DAC, Expected a Bt485 DAC\n"));
goto error1;
}
}
else if ((ulPuConfig & P91_PUC_RAMDAC_TYPE) == P91_PUC_DAC_BT485)
{
if (HwDeviceExtension->Dac.ulDacId != DAC_ID_BT485)
{
VideoDebugPrint((1, "WEITEKP9! WARNING - Detected an BT485 DAC, Expected an IBM525 DAC\n"));
goto error1;
}
}
else if ((ulPuConfig & P91_PUC_RAMDAC_TYPE) == P91_PUC_DAC_BT489)
{
if (HwDeviceExtension->Dac.ulDacId != DAC_ID_BT489)
{
VideoDebugPrint((1, "WEITEKP9! WARNING - Detected an BT489 DAC, Expected an IBM525 DAC\n"));
goto error1;
}
}
else
{
vpCurrStatus = P9_UNSUPPORTED_DAC;
VideoDebugPrint((1, "WEITEKP9! ERROR - Found P9100, detected an unsupported DAC\n"));
goto error1;
}
/*
** SNI-Od: Restore all VGA registers
** after we switch back to VGA mode
*/
VideoDebugPrint((2, "Before 1st write config"));
WeitekP91NapTime();
WriteP9ConfigRegister(HwDeviceExtension,P91_CONFIG_MODE,0x2);
VideoDebugPrint((2, "After wrote config\n"));
VideoDebugPrint((2, "Before restore\n"));
WeitekP91NapTime();
P91RestoreVGAregs(HwDeviceExtension,&VGAregs);
VideoDebugPrint((2, "After restore\n"));
WeitekP91NapTime();
}
//
// Set the Chip, Adapter, DAC, and Memory information in the registry.
//
DevSetRegistryParams(HwDeviceExtension);
//
// Initialize the monitor parameters.
//
HwDeviceExtension->CurrentModeNumber = 0;
//
// Initialize the pointer state flags.
//
HwDeviceExtension->flPtrState = 0;
//
// NOTE:
// Should we free up all the address map we allocated to ourselves ?
// Do we use them after initialization ???
//
// VideoPortFreeDeviceBase(HwDeviceExtension, HwDeviceExtension->Coproc);
// VideoPortFreeDeviceBase(HwDeviceExtension, HwDeviceExtension->Vga);
//
// Indicate a successful completion status.
//
VideoDebugPrint((2, "FindAdapter: succeeded\n"));
if_Not_SIEMENS_P9100_VLB()
VideoPortFreeDeviceBase(HwDeviceExtension, HwDeviceExtension->FrameAddress);
InitializeModes(HwDeviceExtension);
WeitekP91NapTime();
VideoDebugPrint((2, "return\n"));
return(NO_ERROR);
//
// We get here if we really detected a problem, not a mismatch of configuration
//
error1:
if (CoProcId == P9100_ID)
{
P91RestoreVGAregs(HwDeviceExtension,&VGAregs);
VideoDebugPrint((2, "restored vga\n"));
WeitekP91NapTime();
}
if ( vpCurrStatus != NO_ERROR && vpCurrStatus != vpP91AdapterStatus )
{
vpP91AdapterStatus = vpCurrStatus;
VideoPortLogError(HwDeviceExtension,
NULL,
vpCurrStatus,
__LINE__);
}
#if defined(i386)
// Switch back to VGA emulation mode
//
// We need to do this so that the VGA miniport can start up.
//
WriteP9ConfigRegister(HwDeviceExtension, P91_CONFIG_MODE, 0x2);
#endif
VideoDebugPrint((1, "returning ERROR_DEV_NOT_EXIST\n"));
return (ERROR_DEV_NOT_EXIST);
} // end FindAdapter()
VOID
DevSetRegistryParams(PHW_DEVICE_EXTENSION hwDeviceExtension)
{
PUSHORT pwszChip,
pwszDAC,
pwszAdapterString;
ULONG cbChip,
cbDAC,
cbAdapterString,
AdapterMemorySize;
//
// First set the string for the chip type, and set the
// memory configuration if available.
//
if (hwDeviceExtension->P9CoprocInfo.CoprocId == P9000_ID)
{
pwszChip = L"Weitek P9000";
cbChip = sizeof (L"Weitek P9000");
}
else
{
pwszChip = L"Weitek P9100";
cbChip = sizeof (L"Weitek P9100");
}
//
// Set the memory size
//
AdapterMemorySize = hwDeviceExtension->FrameLength;
//
// Now, set the string for the DAC type.
//
if (hwDeviceExtension->Dac.ulDacId == DAC_ID_BT485)
{
pwszDAC = L"Brooktree Bt485";
cbDAC = sizeof (L"Brooktree Bt485");
}
else if (hwDeviceExtension->Dac.ulDacId == DAC_ID_BT489)
{
pwszDAC = L"Brooktree Bt489";
cbDAC = sizeof (L"Brooktree Bt489");
}
else
{
pwszDAC = L"IBM IBM525";
cbDAC = sizeof (L"IBM IBM525");
}
//
// Now just pickup the adapter information from the adapter description.
//
//
// Use the length of the longest string !
//
pwszAdapterString = hwDeviceExtension->AdapterDesc.ausAdapterIDString;
cbAdapterString = sizeof(L"Generic Weitek P9000 VL Adapter");
//
// We now have a complete hardware description of the hardware.
// Save the information to the registry so it can be used by
// configuration programs - such as the display applet
//
VideoPortSetRegistryParameters(hwDeviceExtension,
L"HardwareInformation.ChipType",
pwszChip,
cbChip);
VideoPortSetRegistryParameters(hwDeviceExtension,
L"HardwareInformation.DacType",
pwszDAC,
cbDAC);
VideoPortSetRegistryParameters(hwDeviceExtension,
L"HardwareInformation.MemorySize",
&AdapterMemorySize,
sizeof(ULONG));
VideoPortSetRegistryParameters(hwDeviceExtension,
L"HardwareInformation.AdapterString",
pwszAdapterString,
cbAdapterString);
}
BOOLEAN
P9Initialize(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
This routine does one time initialization of the device.
Arguments:
HwDeviceExtension - Supplies a pointer to the miniport's device extension.
Return Value:
Always returns TRUE since this routine can never fail.
--*/
{
VideoDebugPrint((2, "P9Initialize ----------\n"));
return(TRUE);
} // end P9Initialize()
BOOLEAN
P9StartIO(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVIDEO_REQUEST_PACKET RequestPacket
)
/*++
Routine Description:
This routine is the main execution routine for the miniport driver. It
acceptss a Video Request Packet, performs the request, and then returns
with the appropriate status.
Arguments:
HwDeviceExtension - Supplies a pointer to the miniport's device extension.
RequestPacket - Pointer to the video request packet. This structure
contains all the parameters passed to the VideoIoControl function.
Return Value:
--*/
{
VP_STATUS status;
PVIDEO_MODE_INFORMATION modeInformation;
PVIDEO_MEMORY_INFORMATION memoryInformation;
ULONG inIoSpace;
PVIDEO_CLUT clutBuffer;
PVOID virtualAddr;
UCHAR i;
ULONG numValidModes;
ULONG ulMemoryUsage;
// VideoDebugPrint((2, "StartIO ----------\n"));
//
// Switch on the IoContolCode in the RequestPacket. It indicates which
// function must be performed by the driver.
//
switch (RequestPacket->IoControlCode)
{
case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
VideoDebugPrint((2, "P9StartIO - IOCTL_QUERY_PUBLIC_ACCESS_RANGES\n"));
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_PUBLIC_ACCESS_RANGES)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
break;
}
#if 0
vDumpPCIConfig(HwDeviceExtension,
"P9StartIo - IOCTL_QUERY_PUBLIC_ACCESS_RANGES");
#endif
// map the coproc to a virtual address
//
// Note that on the Alpha we have to map this in sparse-space
// because dense-space requires all reads to be 64 bits, which
// would give us unintended side effects using the Weitek
// registers.
//
{
PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
ULONG CoprocSize = 0x100000;
portAccess = RequestPacket->OutputBuffer;
portAccess->InIoSpace = FALSE;
portAccess->MappedInIoSpace = portAccess->InIoSpace;
portAccess->VirtualAddress = NULL;
status = VideoPortMapMemory(HwDeviceExtension,
HwDeviceExtension->CoprocPhyAddr,
&CoprocSize,
&(portAccess->MappedInIoSpace),
&(portAccess->VirtualAddress));
HwDeviceExtension->CoprocVirtAddr = portAccess->VirtualAddress;
}
status = NO_ERROR;
break;
case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
VideoDebugPrint((2, "P9StartIO - FreePublicAccessRanges\n"));
{
PVIDEO_MEMORY mappedMemory;
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) {
status = ERROR_INSUFFICIENT_BUFFER;
break;
}
mappedMemory = RequestPacket->InputBuffer;
status = NO_ERROR;
if (mappedMemory->RequestedVirtualAddress != NULL)
{
status = VideoPortUnmapMemory(HwDeviceExtension,
mappedMemory->
RequestedVirtualAddress,
0);
}
}
break;
case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
VideoDebugPrint((2, "P9StartIO - MapVideoMemory\n"));
if ( (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_MEMORY_INFORMATION))) ||
(RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
memoryInformation = RequestPacket->OutputBuffer;
memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
(RequestPacket->InputBuffer))->RequestedVirtualAddress;
memoryInformation->VideoRamLength = HwDeviceExtension->FrameLength;
#ifdef ALPHA
//
// On the Alpha, we map the frame buffer in dense-space so that
// we can have GDI draw directly on the surface when we need it
// to.
//
inIoSpace = 4;
#else
inIoSpace = 0;
#endif
status = VideoPortMapMemory(HwDeviceExtension,
HwDeviceExtension->PhysicalFrameAddr,
&(memoryInformation->VideoRamLength),
&inIoSpace,
&(memoryInformation->VideoRamBase));
//
// The frame buffer and virtual memory and equivalent in this
// case.
//
memoryInformation->FrameBufferBase =
memoryInformation->VideoRamBase;
memoryInformation->FrameBufferLength =
memoryInformation->VideoRamLength;
break;
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
VideoDebugPrint((2, "P9StartIO - UnMapVideoMemory\n"));
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
status = VideoPortUnmapMemory(HwDeviceExtension,
((PVIDEO_MEMORY)
(RequestPacket->InputBuffer))->
RequestedVirtualAddress,
0);
break;
case IOCTL_VIDEO_QUERY_CURRENT_MODE:
VideoDebugPrint((2, "P9StartIO - QueryCurrentModes\n"));
modeInformation = RequestPacket->OutputBuffer;
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_MODE_INFORMATION)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
*((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer) =
P9Modes[HwDeviceExtension->CurrentModeNumber].modeInformation;
((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer)->Frequency =
HwDeviceExtension->VideoData.vlr;
if (HwDeviceExtension->P9CoprocInfo.CoprocId == P9000_ID)
{
((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer)->DriverSpecificAttributeFlags =
CAPS_WEITEK_CHIPTYPE_IS_P9000;
}
else
{
((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer)->DriverSpecificAttributeFlags =
0;
}
status = NO_ERROR;
}
break;
case IOCTL_VIDEO_QUERY_AVAIL_MODES:
VideoDebugPrint((2, "P9StartIO - QueryAvailableModes\n"));
numValidModes = HwDeviceExtension->ulNumAvailModes;
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
numValidModes * sizeof(VIDEO_MODE_INFORMATION)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
ULONG Flags=0;
if (HwDeviceExtension->P9CoprocInfo.CoprocId == P9000_ID)
{
Flags = CAPS_WEITEK_CHIPTYPE_IS_P9000;
}
modeInformation = RequestPacket->OutputBuffer;
for (i = 0; i < mP9ModeCount; i++)
{
if (P9Modes[i].valid == TRUE)
{
*modeInformation = P9Modes[i].modeInformation;
modeInformation->DriverSpecificAttributeFlags = Flags;
modeInformation++;
}
}
status = NO_ERROR;
}
break;
case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
VideoDebugPrint((2, "P9StartIO - QueryNumAvailableModes\n"));
//
// Find out the size of the data to be put in the the buffer and
// return that in the status information (whether or not the
// information is there). If the buffer passed in is not large
// enough return an appropriate error code.
//
// !!! This must be changed to take into account which monitor
// is present on the machine.
//
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_NUM_MODES)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes =
HwDeviceExtension->ulNumAvailModes;
((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength =
sizeof(VIDEO_MODE_INFORMATION);
status = NO_ERROR;
}
break;
case IOCTL_VIDEO_SET_CURRENT_MODE:
VideoDebugPrint((2, "P9StartIO - SetCurrentMode\n"));
//
// verify data
// !!! Make sure it is one of the valid modes on the list
// calculated using the monitor information.
//
if (((PVIDEO_MODE)(RequestPacket->InputBuffer))->RequestedMode
>= mP9ModeCount)
{
status = ERROR_INVALID_PARAMETER;
break;
}
HwDeviceExtension->CurrentModeNumber =
*(ULONG *)(RequestPacket->InputBuffer);
DevInitP9(HwDeviceExtension);
#if 0
vDumpPCIConfig(HwDeviceExtension,
"P9StartIo - IOCTL_VIDEO_SET_CURRENT_MODE");
#endif
status = NO_ERROR;
break;
case IOCTL_VIDEO_SET_COLOR_REGISTERS:
VideoDebugPrint((2, "P9StartIO - SetColorRegs\n"));
clutBuffer = RequestPacket->InputBuffer;
//
// Check if the size of the data in the input buffer is large enough.
//
if ( (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) -
sizeof(ULONG)) ||
(RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) +
(sizeof(ULONG) * (clutBuffer->NumEntries - 1)) ) )
{
status = ERROR_INSUFFICIENT_BUFFER;
break;
}
if (P9Modes[HwDeviceExtension->CurrentModeNumber].
modeInformation.BitsPerPlane == 8)
{
HwDeviceExtension->Dac.DACSetPalette(HwDeviceExtension,
(PULONG)clutBuffer->LookupTable,
clutBuffer->FirstEntry,
clutBuffer->NumEntries);
status = NO_ERROR;
}
break;
case IOCTL_VIDEO_ENABLE_POINTER:
{
ULONG iCount = (CURSOR_WIDTH * CURSOR_HEIGHT * 2) / 8;
ULONG xInitPos, yInitPos;
VideoDebugPrint((2, "P9StartIO - EnablePointer\n"));
xInitPos = P9Modes[HwDeviceExtension->CurrentModeNumber].
modeInformation.VisScreenWidth / 2;
yInitPos = P9Modes[HwDeviceExtension->CurrentModeNumber].
modeInformation.VisScreenHeight / 2;
HwDeviceExtension->Dac.HwPointerSetPos(HwDeviceExtension, xInitPos, yInitPos);
HwDeviceExtension->Dac.HwPointerOn(HwDeviceExtension);
status = NO_ERROR;
break;
case IOCTL_VIDEO_DISABLE_POINTER:
VideoDebugPrint((2, "P9StartIO - DisablePointer\n"));
HwDeviceExtension->Dac.HwPointerOff(HwDeviceExtension);
status = NO_ERROR;
break;
}
case IOCTL_VIDEO_SET_POINTER_POSITION:
{
PVIDEO_POINTER_POSITION pointerPosition;
pointerPosition = RequestPacket->InputBuffer;
//
// Check if the size of the data in the input buffer is large enough.
//
if (RequestPacket->InputBufferLength < sizeof(VIDEO_POINTER_POSITION))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
HwDeviceExtension->ulPointerX = (ULONG)pointerPosition->Row;
HwDeviceExtension->ulPointerY = (ULONG)pointerPosition->Column;
HwDeviceExtension->Dac.HwPointerSetPos(HwDeviceExtension,
(ULONG)pointerPosition->Column,
(ULONG)pointerPosition->Row);
status = NO_ERROR;
}
break;
}
case IOCTL_VIDEO_QUERY_POINTER_POSITION:
{
PVIDEO_POINTER_POSITION pPointerPosition = RequestPacket->OutputBuffer;
VideoDebugPrint((2, "P9StartIO - QuerypointerPostion\n"));
//
// Make sure the output buffer is big enough.
//
if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_POSITION))
{
RequestPacket->StatusBlock->Information = 0;
return ERROR_INSUFFICIENT_BUFFER;
}
//
// Return the pointer position
//
pPointerPosition->Row = (SHORT)HwDeviceExtension->ulPointerX;
pPointerPosition->Column = (SHORT)HwDeviceExtension->ulPointerY;
RequestPacket->StatusBlock->Information =
sizeof(VIDEO_POINTER_POSITION);
status = NO_ERROR;
break;
}
case IOCTL_VIDEO_SET_POINTER_ATTR: // Set pointer shape
{
PVIDEO_POINTER_ATTRIBUTES pointerAttributes;
UCHAR *pHWCursorShape; // Temp Buffer
VideoDebugPrint((2, "P9StartIO - SetPointerAttributes\n"));
pointerAttributes = RequestPacket->InputBuffer;
//
// Check if the size of the data in the input buffer is large enough.
//
if (RequestPacket->InputBufferLength <
(sizeof(VIDEO_POINTER_ATTRIBUTES) + ((sizeof(UCHAR) *
(CURSOR_WIDTH/8) * CURSOR_HEIGHT) * 2)))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
//
// If the specified cursor width or height is not valid, then
// return an invalid parameter error.
//
else if ((pointerAttributes->Width > CURSOR_WIDTH) ||
(pointerAttributes->Height > CURSOR_HEIGHT))
{
status = ERROR_INVALID_PARAMETER;
}
else if (pointerAttributes->Flags & VIDEO_MODE_MONO_POINTER)
{
pHWCursorShape = (PUCHAR) &pointerAttributes->Pixels[0];
//
// If this is an animated pointer, don't turn the hw
// pointer off. This will eliminate cursor blinking.
// Since GDI currently doesn't pass the ANIMATE_START
// flag, also check to see if the state of the
// ANIMATE_UPDATE flag has changed from the last call.
// If it has, turn the pointer off to eliminate ptr
// "jumping" when the ptr shape is changed.
//
if (!(pointerAttributes->Flags & VIDEO_MODE_ANIMATE_UPDATE) ||
((HwDeviceExtension->flPtrState ^
pointerAttributes->Flags) & VIDEO_MODE_ANIMATE_UPDATE))
{
HwDeviceExtension->Dac.HwPointerOff(HwDeviceExtension);
}
//
// Update the cursor state flags in the Device Extension.
//
HwDeviceExtension->flPtrState = pointerAttributes->Flags;
HwDeviceExtension->Dac.HwPointerSetShape(HwDeviceExtension,
pHWCursorShape);
HwDeviceExtension->Dac.HwPointerSetPos(HwDeviceExtension,
(ULONG)pointerAttributes->Column,
(ULONG)pointerAttributes->Row);
HwDeviceExtension->Dac.HwPointerOn(HwDeviceExtension);
status = NO_ERROR;
break;
}
else
{
//
// This cursor is unsupported. Return an error.
//
status = ERROR_INVALID_PARAMETER;
}
//
// Couldn't set the new cursor shape. Ensure that any existing HW
// cursor is disabled.
//
HwDeviceExtension->Dac.HwPointerOff(HwDeviceExtension);
break;
}
case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
{
PVIDEO_POINTER_CAPABILITIES pointerCaps = RequestPacket->OutputBuffer;
VideoDebugPrint((2, "P9StartIO - QueryPointerCapabilities\n"));
if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_CAPABILITIES))
{
RequestPacket->StatusBlock->Information = 0;
status = ERROR_INSUFFICIENT_BUFFER;
}
pointerCaps->Flags = VIDEO_MODE_MONO_POINTER;
pointerCaps->MaxWidth = CURSOR_WIDTH;
pointerCaps->MaxHeight = CURSOR_HEIGHT;
pointerCaps->HWPtrBitmapStart = 0; // No VRAM storage for pointer
pointerCaps->HWPtrBitmapEnd = 0;
//
// Number of bytes we're returning.
//
RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_CAPABILITIES);
status = NO_ERROR;
break;
}
case IOCTL_VIDEO_RESET_DEVICE:
VideoDebugPrint((2, "P9StartIO - RESET_DEVICE\n"));
DevDisableP9(HwDeviceExtension, FALSE);
status = NO_ERROR;
break;
case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
{
PVIDEO_SHARE_MEMORY pShareMemory;
PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
PHYSICAL_ADDRESS shareAddress;
PVOID virtualAddress;
ULONG sharedViewSize;
VideoDebugPrint((2, "P9StartIo - ShareVideoMemory\n"));
if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) ||
(RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
VideoDebugPrint((1, "IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INSUFFICIENT_BUFFER\n"));
status = ERROR_INSUFFICIENT_BUFFER;
break;
}
pShareMemory = RequestPacket->InputBuffer;
if ( (pShareMemory->ViewOffset > HwDeviceExtension->FrameLength) ||
((pShareMemory->ViewOffset + pShareMemory->ViewSize) >
HwDeviceExtension->FrameLength) ) {
VideoDebugPrint((1, "IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INVALID_PARAMETER\n"));
status = ERROR_INVALID_PARAMETER;
break;
}
RequestPacket->StatusBlock->Information =
sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
//
// Beware: the input buffer and the output buffer are the same
// buffer, and therefore data should not be copied from one to the
// other
//
virtualAddress = pShareMemory->ProcessHandle;
sharedViewSize = pShareMemory->ViewSize;
#ifdef ALPHA
//
// On the Alpha, we map the frame buffer in dense-space so that
// we can have GDI draw directly on the surface when we need it
// to.
//
inIoSpace = 4;
#else
inIoSpace = 0;
#endif
//
// NOTE: we are ignoring ViewOffset
//
shareAddress.QuadPart =
HwDeviceExtension->PhysicalFrameAddr.QuadPart;
//
// The frame buffer is always mapped linearly.
//
status = VideoPortMapMemory(HwDeviceExtension,
shareAddress,
&sharedViewSize,
&inIoSpace,
&virtualAddress);
pShareMemoryInformation = RequestPacket->OutputBuffer;
pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
pShareMemoryInformation->VirtualAddress = virtualAddress;
pShareMemoryInformation->SharedViewSize = sharedViewSize;
break;
}
case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
{
PVIDEO_SHARE_MEMORY pShareMemory;
VideoDebugPrint((2, "P9StartIo - UnshareVideoMemory\n"));
if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY)) {
status = ERROR_INSUFFICIENT_BUFFER;
break;
}
pShareMemory = RequestPacket->InputBuffer;
status = VideoPortUnmapMemory(HwDeviceExtension,
pShareMemory->RequestedVirtualAddress,
pShareMemory->ProcessHandle);
break;
}
//
// if we get here, an invalid IoControlCode was specified.
//
default:
VideoDebugPrint((1, "Fell through P9 startIO routine - invalid command\n"));
status = ERROR_INVALID_FUNCTION;
break;
}
RequestPacket->StatusBlock->Status = status;
return(TRUE);
} // end P9StartIO()
VOID
DevInitP9(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Sets the video mode described in the device extension.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
--*/
{
VideoDebugPrint((2, "DevInitP9 ----------\n"));
//
// Copy the default parameters for this resolution mode into the
// device extension.
//
VideoPortMoveMemory((PVOID) &(HwDeviceExtension->VideoData),
(PVOID) P9Modes[HwDeviceExtension->CurrentModeNumber].pvData,
sizeof(VDATA));
//
// Store the requested Bits/Pixel value in the video parms structure
// in the Device Extension.
//
HwDeviceExtension->usBitsPixel =
P9Modes[HwDeviceExtension->CurrentModeNumber].modeInformation.BitsPerPlane *
P9Modes[HwDeviceExtension->CurrentModeNumber].modeInformation.NumberOfPlanes;
HwDeviceExtension->AdapterDesc.OEMSetMode(HwDeviceExtension);
if (HwDeviceExtension->P9CoprocInfo.CoprocId == P9000_ID)
{
Init8720(HwDeviceExtension);
//
// Initialize the P9000 system configuration register.
//
SysConf(HwDeviceExtension);
//
// Set the P9000 Crtc timing registers.
//
WriteTiming(HwDeviceExtension);
}
else
{
InitP9100(HwDeviceExtension);
P91_SysConf(HwDeviceExtension);
P91_WriteTiming(HwDeviceExtension);
}
VideoDebugPrint((2, "DevInitP9 ---done---\n"));
}
BOOLEAN
P9ResetVideo(
IN PVOID HwDeviceExtension,
IN ULONG Columns,
IN ULONG Rows
)
/*++
routine description:
disables the P9 and turns on vga pass-thru.
This function is exported as the HwResetHw entry point so that it may be
called by the Video Port driver
at bugcheck time so that VGA video may be enabled.
arguments:
hwdeviceextension - pointer to the miniport driver's device extension.
Columns - Number of columns for text mode (not used).
Rows - Number of rows for text mode (not used).
return value:
Always returns FALSE so that the Video Port driver will call Int 10 to
set the desired video mode.
--*/
{
DevDisableP9(HwDeviceExtension, TRUE);
//
// Tell the Video Port driver to do an Int 10 mode set.
//
return(FALSE);
}
VOID
DevDisableP9(
PHW_DEVICE_EXTENSION HwDeviceExtension,
BOOLEAN BugCheck
)
{
PHYSICAL_ADDRESS Base;
BOOLEAN bResetComplete;
//
// Clean up the DAC.
//
HwDeviceExtension->Dac.DACRestore(HwDeviceExtension);
//
// If we are not about to "bugcheck", then clear out
// video memory.
//
// NOTE: On the alpha, the attempt to clear video memory causes
// the machine to hang. So, we just won't clear the memory
// on the alpha.
//
#if !defined(_ALPHA_)
if (BugCheck == FALSE)
{
Base = DriverAccessRanges[0].RangeStart;
Base.QuadPart += HwDeviceExtension->P9CoprocInfo.FrameBufOffset;
HwDeviceExtension->FrameAddress =
VideoPortGetDeviceBase(HwDeviceExtension,
Base,
HwDeviceExtension->P9CoprocInfo.AddrSpace -
HwDeviceExtension->P9CoprocInfo.FrameBufOffset,
DriverAccessRanges[0].RangeInIoSpace);
if (HwDeviceExtension->FrameAddress != NULL)
{
VideoDebugPrint((2, "Weitekp9: Clearing video memory.\n"));
VideoPortZeroMemory(HwDeviceExtension->FrameAddress,
HwDeviceExtension->FrameLength);
VideoPortFreeDeviceBase(HwDeviceExtension, HwDeviceExtension->FrameAddress);
}
}
#endif
// NOTE: On the P9100 we must take care of the DAC before
// we change the mode to emulation.
// !!! This must be tested on the P9000
bResetComplete = HwDeviceExtension->AdapterDesc.P9DisableVideo(HwDeviceExtension);
//
// We only want to call int10 if the reset function needs some help and
// we are not in bugcheck mode, because int10 does not work in bugcheck
// mode.
//
if ((bResetComplete == FALSE) &&
(BugCheck == FALSE))
{
#ifndef PPC
VIDEO_X86_BIOS_ARGUMENTS biosArguments;
//
// Now simply do an int10 and switch to mode 3. The video BIOS
// will do the work.
//
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
biosArguments.Eax = 0x0003;
VideoPortInt10(HwDeviceExtension, &biosArguments);
#endif
}
}
VOID
InitializeModes(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
This routine walks through the list of modes, and determines which
modes will work with our hardware. It sets a flag for each mode
which will work, and places the number of valid modes in the
HwDeviceExtension.
Arguments:
HwDeviceExtension - pointer to the miniport driver's device extension.
Columns - Number of columns for text mode (not used).
Rows - Number of rows for text mode (not used).
Return Value:
none
--*/
{
int i;
ULONG numValidModes=0;
for(i=0; i<mP9ModeCount; i++)
{
if ((HwDeviceExtension->FrameLength >=
P9Modes[i].modeInformation.ScreenStride *
P9Modes[i].modeInformation.VisScreenHeight) &&
(HwDeviceExtension->P9CoprocInfo.CoprocId &
P9Modes[i].ulChips) &&
((P9Modes[i].modeInformation.BitsPerPlane != 24) ||
(HwDeviceExtension->Dac.bRamdac24BPP)) )
{
if_SIEMENS_VLB()
{
P9Modes[i].modeInformation.AttributeFlags |=
VIDEO_MODE_NO_64_BIT_ACCESS;
}
P9Modes[i].valid = TRUE;
numValidModes++;
}
}
//
// store the number of valid modes in the HwDeviceExtension
// so we can quickly look it up later when we need it.
//
HwDeviceExtension->ulNumAvailModes = numValidModes;
}
//
// Global Functions.
//
long mul32(
short op1,
short op2
)
{
return ( ((long) op1) * ((long) op2));
}
int div32(
long op1,
short op2
)
{
return ( (int) (op1 / (long) op2));
}
#if (_WIN32_WINNT >= 500)
//
// Routine to set a desired DPMS power management state.
//
VP_STATUS
WP9SetPower50(
PHW_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
)
{
if ((pVideoPowerMgmt->PowerState == VideoPowerOn) ||
(pVideoPowerMgmt->PowerState == VideoPowerHibernate) ||
(pVideoPowerMgmt->PowerState == VideoPowerStandBy)
) {
return NO_ERROR;
} else {
return ERROR_INVALID_FUNCTION;
}
}
//
// Routine to retrieve possible DPMS power management states.
//
VP_STATUS
WP9GetPower50(
PHW_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
)
{
if ((pVideoPowerMgmt->PowerState == VideoPowerOn) ||
(pVideoPowerMgmt->PowerState == VideoPowerHibernate)) {
return NO_ERROR;
} else {
return ERROR_INVALID_FUNCTION;
}
}
//
// Routine to retrieve the Enhanced Display ID structure via DDC
//
ULONG
WP9GetVideoChildDescriptor(
PVOID HwDeviceExtension,
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
PVIDEO_CHILD_TYPE pChildType,
PVOID pvChildDescriptor,
PULONG pHwId,
PULONG pUnused
)
{
PHW_DEVICE_EXTENSION pHwDeviceExtension = HwDeviceExtension;
ULONG Status;
ASSERT(pHwDeviceExtension != NULL && pMoreChildren != NULL);
VideoDebugPrint((2, "weitekp9 GetVideoChildDescriptor: *** Entry point ***\n"));
//
// Determine if the graphics adapter in the system supports
// DDC2 (our miniport only supports DDC2, not DDC1). This has
// the side effect (assuming both monitor and card support
// DDC2) of switching the monitor from DDC1 mode (repeated
// "blind" broadcast of EDID clocked by the vertical sync
// signal) to DDC2 mode (query/response not using any of the
// normal video lines - can transfer information rapidly
// without first disrupting the screen by switching into
// a pseudo-mode with a high vertical sync frequency).
//
// Since we must support hot-plugging of monitors, and our
// routine to obtain the EDID structure via DDC2 assumes that
// the monitor is in DDC2 mode, we must make this test each
// time this entry point is called.
//
switch (ChildEnumInfo->ChildIndex) {
case 0:
//
// Case 0 is used to enumerate devices found by the ACPI firmware.
//
// Since we do not support ACPI devices yet, we must return failure.
//
Status = ERROR_NO_MORE_DEVICES;
break;
case 1:
//
// We do not support monitor enumeration
//
Status = ERROR_NO_MORE_DEVICES;
break;
case DISPLAY_ADAPTER_HW_ID:
{
PUSHORT pPnpDeviceDescription = NULL;
ULONG stringSize = sizeof(L"*PNPXXXX");
//
// Special ID to handle return legacy PnP IDs for root enumerated
// devices.
//
*pChildType = VideoChip;
*pHwId = DISPLAY_ADAPTER_HW_ID;
//
// Figure out which card type and set pPnpDeviceDescription at
// associated string.
//
// WTK_9100_ID 0x0002
if (pHwDeviceExtension->P9CoprocInfo.CoprocId == P9100_ID)
pPnpDeviceDescription = L"*PNP0002";
// WTK_9002_ID 0x9002
else if (pHwDeviceExtension->P9CoprocInfo.CoprocId == P9000_ID )
pPnpDeviceDescription = L"*PNP9002";
else {
VideoDebugPrint((1, "weitekp9.sys coprocId:%x\n",
pHwDeviceExtension->P9CoprocInfo.CoprocId));
}
//
// Now just copy the string into memory provided.
//
if (pPnpDeviceDescription)
memcpy(pvChildDescriptor, pPnpDeviceDescription, stringSize);
Status = ERROR_MORE_DATA;
break;
}
default:
Status = ERROR_NO_MORE_DEVICES;
break;
}
return Status;
}
#endif // _WIN32_WINNT >= 500