1668 lines
33 KiB
C
1668 lines
33 KiB
C
/*++
|
||
|
||
Copyright (c) 1990-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ops.c
|
||
|
||
Abstract:
|
||
|
||
video port stub routines for memory and io.
|
||
|
||
Author:
|
||
|
||
Andre Vachon (andreva) 22-Feb-1997
|
||
|
||
Environment:
|
||
|
||
kernel mode only
|
||
|
||
Notes:
|
||
|
||
This module is a driver which implements OS dependant functions on the
|
||
behalf of the video drivers
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "videoprt.h"
|
||
|
||
#pragma alloc_text(PAGE,VideoPortGetAssociatedDeviceExtension)
|
||
#pragma alloc_text(PAGE,VideoPortAcquireDeviceLock)
|
||
#pragma alloc_text(PAGE,VideoPortReleaseDeviceLock)
|
||
#pragma alloc_text(PAGE,VideoPortGetRomImage)
|
||
#pragma alloc_text(PAGE,VpGetBusInterface)
|
||
#pragma alloc_text(PAGE,VideoPortGetVgaStatus)
|
||
#pragma alloc_text(PAGE,pVideoPortGetVgaStatusPci)
|
||
|
||
//
|
||
//ULONG
|
||
//VideoPortCompareMemory (
|
||
// PVOID Source1,
|
||
// PVOID Source2,
|
||
// ULONG Length
|
||
// )
|
||
//Forwarded to RtlCompareMemory(Source1,Source2,Length);
|
||
//
|
||
|
||
|
||
VP_STATUS
|
||
VideoPortDisableInterrupt(
|
||
IN PVOID HwDeviceExtension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortDisableInterrupt allows a miniport driver to disable interrupts
|
||
from its adapter. This means that the interrupts coming from the device
|
||
will be ignored by the operating system and therefore not forwarded to
|
||
the driver.
|
||
|
||
A call to this function is valid only if the interrupt is defined, in
|
||
other words, if the appropriate data was provided at initialization
|
||
time to set up the interrupt. Interrupts will remain disabled until
|
||
they are reenabled using the VideoPortEnableInterrupt function.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Points to the miniport driver's device extension.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR if the function completes successfully.
|
||
|
||
ERROR_INVALID_FUNCTION if the interrupt cannot be disabled because it
|
||
was not set up at initialization.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
//
|
||
// Only perform this operation if the interurpt is actually connected.
|
||
//
|
||
|
||
if (fdoExtension->InterruptObject) {
|
||
|
||
HalDisableSystemInterrupt(fdoExtension->InterruptVector,
|
||
fdoExtension->InterruptIrql);
|
||
|
||
fdoExtension->InterruptsEnabled = FALSE;
|
||
|
||
return NO_ERROR;
|
||
|
||
} else {
|
||
|
||
return ERROR_INVALID_FUNCTION;
|
||
|
||
}
|
||
|
||
} // VideoPortDisableInterrupt()
|
||
|
||
|
||
VP_STATUS
|
||
VideoPortEnableInterrupt(
|
||
IN PVOID HwDeviceExtension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortEnableInterrupt allows a miniport driver to enable interrupts
|
||
from its adapter. A call to this function is valid only if the
|
||
interrupt is defined, in other words, if the appropriate data was
|
||
provided at initialization time to set up the interrupt.
|
||
|
||
This function is used to re-enable interrupts if they have been disabled
|
||
using VideoPortDisableInterrupt.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Points to the miniport driver's device extension.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR if the function completes successfully.
|
||
|
||
ERROR_INVALID_FUNCTION if the interrupt cannot be disabled because it
|
||
was not set up at initialization.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
//
|
||
// Only perform this operation if the interurpt is actually connected.
|
||
//
|
||
|
||
if (fdoExtension->InterruptObject) {
|
||
|
||
fdoExtension->InterruptsEnabled = TRUE;
|
||
|
||
HalEnableSystemInterrupt(fdoExtension->InterruptVector,
|
||
fdoExtension->InterruptIrql,
|
||
fdoExtension->InterruptMode);
|
||
|
||
return NO_ERROR;
|
||
|
||
} else {
|
||
|
||
return ERROR_INVALID_FUNCTION;
|
||
|
||
}
|
||
|
||
} // VideoPortEnableInterrupt()
|
||
|
||
PVOID
|
||
VideoPortGetRomImage(
|
||
IN PVOID HwDeviceExtension,
|
||
IN PVOID Unused1,
|
||
IN ULONG Unused2,
|
||
IN ULONG Length
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows a miniport driver to get a copy of its devices
|
||
ROM. This function returns the pointer to a buffer containing the
|
||
devices ROM.
|
||
|
||
Arguments;
|
||
|
||
HwDeviceExtension - Points to the miniport driver's device extension.
|
||
|
||
Unused1 - Reserved for future use. Must be NULL. (Buffer)
|
||
|
||
Unused2 - Reserved for future use. Must be zero. (Offset)
|
||
|
||
Length - Number of bytes to return.
|
||
|
||
--*/
|
||
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
|
||
ULONG
|
||
VideoPortGetBusData(
|
||
PVOID HwDeviceExtension,
|
||
IN BUS_DATA_TYPE BusDataType,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
|
||
{
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
//
|
||
// Issue a warning telling the miniport they should not read everything
|
||
// out of the driver config space otherwise it causes some device like
|
||
// NCR SCSIs to crash.
|
||
//
|
||
|
||
#if DBG
|
||
if ((BusDataType == PCIConfiguration) &&
|
||
(Length >= sizeof(PCI_COMMON_CONFIG)))
|
||
{
|
||
pVideoDebugPrint((0, "A miniport must only call VideoPortGetBusData with PCI_COMMON_HDR_LENGTH\n"));
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
if ((fdoExtension->Flags & LEGACY_DRIVER) ||
|
||
(BusDataType != PCIConfiguration)) {
|
||
|
||
#if defined(NO_LEGACY_DRIVERS)
|
||
pVideoDebugPrint((0, "VideoPortGetBusData: fdoExtension->Flags & LEGACY_DRIVER not supported for 64-bits.\n"));
|
||
|
||
return 0;
|
||
|
||
#else
|
||
return HalGetBusDataByOffset(BusDataType,
|
||
fdoExtension->SystemIoBusNumber,
|
||
SlotNumber,
|
||
Buffer,
|
||
Offset,
|
||
Length);
|
||
#endif // NO_LEGACY_DRIVERS
|
||
|
||
} else {
|
||
|
||
if (fdoExtension->ValidBusInterface) {
|
||
Length = fdoExtension->BusInterface.GetBusData(
|
||
fdoExtension->BusInterface.Context,
|
||
PCI_WHICHSPACE_CONFIG,
|
||
Buffer,
|
||
Offset,
|
||
Length);
|
||
|
||
return Length;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
} // end VideoPortGetBusData()
|
||
|
||
|
||
//
|
||
//UCHAR
|
||
//VideoPortGetCurrentIrql(
|
||
// )
|
||
//Forwarded to KeGetCurrentIrql();
|
||
//
|
||
|
||
|
||
//
|
||
//VOID
|
||
//VideoPortMoveMemory(
|
||
// IN PVOID Destination,
|
||
// IN PVOID Source,
|
||
// IN ULONG Length
|
||
// )
|
||
//
|
||
//Forwarded to RtlMoveMemory(Destination,Source,Length);
|
||
//
|
||
|
||
|
||
//
|
||
// ALL the functions to read ports and registers are forwarded on free
|
||
// builds on x86 and ALPHA to the appropriate kernel function.
|
||
// This saves time and memory
|
||
//
|
||
|
||
#if (DBG || (!defined(_X86_) && !defined(_ALPHA_)))
|
||
|
||
UCHAR
|
||
VideoPortReadPortUchar(
|
||
IN PUCHAR Port
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadPortUchar reads a byte from the specified port address.
|
||
It requires a logical port address obtained from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Return Value:
|
||
|
||
This function returns the byte read from the specified port address.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
UCHAR temp;
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
temp = READ_PORT_UCHAR(Port);
|
||
|
||
pVideoDebugPrint((3,"VideoPortReadPortUchar %x = %x\n", Port, temp));
|
||
|
||
return(temp);
|
||
|
||
} // VideoPortReadPortUchar()
|
||
|
||
USHORT
|
||
VideoPortReadPortUshort(
|
||
IN PUSHORT Port
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadPortUshort reads a word from the specified port address.
|
||
It requires a logical port address obtained from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
|
||
Return Value:
|
||
|
||
This function returns the word read from the specified port address.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
USHORT temp;
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
temp = READ_PORT_USHORT(Port);
|
||
|
||
pVideoDebugPrint((3,"VideoPortReadPortUshort %x = %x\n", Port, temp));
|
||
|
||
return(temp);
|
||
|
||
} // VideoPortReadPortUshort()
|
||
|
||
ULONG
|
||
VideoPortReadPortUlong(
|
||
IN PULONG Port
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadPortUlong reads a double word from the specified port
|
||
address. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Return Value:
|
||
|
||
This function returns the double word read from the specified port address.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG temp;
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
temp = READ_PORT_ULONG(Port);
|
||
|
||
pVideoDebugPrint((3,"VideoPortReadPortUlong %x = %x\n", Port, temp));
|
||
|
||
return(temp);
|
||
|
||
} // VideoPortReadPortUlong()
|
||
|
||
VOID
|
||
VideoPortReadPortBufferUchar(
|
||
IN PUCHAR Port,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadPortBufferUchar reads a number of bytes from a single port
|
||
into a buffer. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Buffer - Points to an array of UCHAR values into which the values are
|
||
stored.
|
||
|
||
Count - Specifes the number of bytes to be read into the buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
pVideoDebugPrint((3,"VideoPortReadPortBufferUchar %x\n", Port));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
READ_PORT_BUFFER_UCHAR(Port, Buffer, Count);
|
||
|
||
} // VideoPortReadPortBufferUchar()
|
||
|
||
VOID
|
||
VideoPortReadPortBufferUshort(
|
||
IN PUSHORT Port,
|
||
IN PUSHORT Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadPortBufferUshort reads a number of words from a single port
|
||
into a buffer. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Buffer - Points to an array of words into which the values are stored.
|
||
|
||
Count - Specifies the number of words to be read into the buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
pVideoDebugPrint((3,"VideoPortReadPortBufferUshort %x\n", Port));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
READ_PORT_BUFFER_USHORT(Port, Buffer, Count);
|
||
|
||
} // VideoPortReadPortBufferUshort()
|
||
|
||
VOID
|
||
VideoPortReadPortBufferUlong(
|
||
IN PULONG Port,
|
||
IN PULONG Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadPortBufferUlong reads a number of double words from a
|
||
single port into a buffer. It requires a logical port address obtained
|
||
from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Buffer - Points to an array of double words into which the values are
|
||
stored.
|
||
|
||
Count - Specifies the number of double words to be read into the buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
pVideoDebugPrint((3,"VideoPortReadPortBufferUlong %x\n", Port));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
READ_PORT_BUFFER_ULONG(Port, Buffer, Count);
|
||
|
||
} // VideoPortReadPortBufferUlong()
|
||
|
||
UCHAR
|
||
VideoPortReadRegisterUchar(
|
||
IN PUCHAR Register
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadRegisterUchar reads a byte from the specified register
|
||
address. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Register - Specifies the register address.
|
||
|
||
Return Value:
|
||
|
||
This function returns the byte read from the specified register address.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
UCHAR temp;
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
temp = READ_REGISTER_UCHAR(Register);
|
||
|
||
pVideoDebugPrint((3,"VideoPortReadRegisterUchar %x = %x\n", Register, temp));
|
||
|
||
return(temp);
|
||
|
||
} // VideoPortReadRegisterUchar()
|
||
|
||
USHORT
|
||
VideoPortReadRegisterUshort(
|
||
IN PUSHORT Register
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadRegisterUshort reads a word from the specified register
|
||
address. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Register - Specifies the register address.
|
||
|
||
Return Value:
|
||
|
||
This function returns the word read from the specified register address.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
USHORT temp;
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
temp = READ_REGISTER_USHORT(Register);
|
||
|
||
pVideoDebugPrint((3,"VideoPortReadRegisterUshort %x = %x\n", Register, temp));
|
||
|
||
return(temp);
|
||
|
||
} // VideoPortReadRegisterUshort()
|
||
|
||
ULONG
|
||
VideoPortReadRegisterUlong(
|
||
IN PULONG Register
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortReadRegisterUlong reads a double word from the specified
|
||
register address. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Register - Specifies the register address.
|
||
|
||
Return Value:
|
||
|
||
This function returns the double word read from the specified register
|
||
address.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG temp;
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
temp = READ_REGISTER_ULONG(Register);
|
||
|
||
pVideoDebugPrint((3,"VideoPortReadRegisterUlong %x = %x\n", Register, temp));
|
||
|
||
return(temp);
|
||
|
||
} // VideoPortReadRegisterUlong()
|
||
|
||
VOID
|
||
VideoPortReadRegisterBufferUchar(
|
||
IN PUCHAR Register,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Read a buffer of unsigned bytes from the specified register address.
|
||
|
||
Arguments:
|
||
|
||
Register - Supplies a pointer to the port address.
|
||
Buffer - Supplies a pointer to the data buffer area.
|
||
Count - The count of items to move.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
|
||
|
||
}
|
||
|
||
VOID
|
||
VideoPortReadRegisterBufferUshort(
|
||
IN PUSHORT Register,
|
||
IN PUSHORT Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Read a buffer of unsigned shorts from the specified register address.
|
||
|
||
Arguments:
|
||
|
||
Register - Supplies a pointer to the port address.
|
||
Buffer - Supplies a pointer to the data buffer area.
|
||
Count - The count of items to move.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
|
||
|
||
}
|
||
|
||
VOID
|
||
VideoPortReadRegisterBufferUlong(
|
||
IN PULONG Register,
|
||
IN PULONG Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Read a buffer of unsigned longs from the specified register address.
|
||
|
||
Arguments:
|
||
|
||
Register - Supplies a pointer to the port address.
|
||
Buffer - Supplies a pointer to the data buffer area.
|
||
Count - The count of items to move.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
|
||
|
||
}
|
||
|
||
#endif // (DBG || (!defined(_X86_) && !defined(_ALPHA_)))
|
||
|
||
|
||
ULONG
|
||
VideoPortSetBusData(
|
||
PVOID HwDeviceExtension,
|
||
IN BUS_DATA_TYPE BusDataType,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
|
||
{
|
||
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
if ((fdoExtension->Flags & LEGACY_DRIVER) ||
|
||
(BusDataType != PCIConfiguration)) {
|
||
|
||
#if defined(NO_LEGACY_DRIVERS)
|
||
pVideoDebugPrint((0, "VideoPortGetBusData: fdoExtension->Flags & LEGACY_DRIVER not supported for 64-bits.\n"));
|
||
|
||
return 0;
|
||
|
||
#else
|
||
|
||
return HalSetBusDataByOffset(BusDataType,
|
||
fdoExtension->SystemIoBusNumber,
|
||
SlotNumber,
|
||
Buffer,
|
||
Offset,
|
||
Length);
|
||
#endif // NO_LEGACY_DRIVERS
|
||
|
||
} else {
|
||
|
||
if (fdoExtension->ValidBusInterface) {
|
||
Length = fdoExtension->BusInterface.SetBusData(
|
||
fdoExtension->BusInterface.Context,
|
||
PCI_WHICHSPACE_CONFIG,
|
||
Buffer,
|
||
Offset,
|
||
Length);
|
||
|
||
return Length;
|
||
} else {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
} // end VideoPortSetBusData()
|
||
|
||
|
||
//
|
||
//VOID
|
||
//VideoPortStallExecution(
|
||
// IN ULONG Microseconds
|
||
// )
|
||
//
|
||
//Forwarded to KeStallExecutionProcessor(Microseconds);
|
||
//
|
||
|
||
|
||
|
||
//
|
||
// ALL the functions to write ports and registers are forwarded on free
|
||
// builds on x86 to the appropriate kernel function.
|
||
// This saves time and memory
|
||
//
|
||
|
||
#if (DBG || (!defined(_X86_) && !defined(_ALPHA_)))
|
||
|
||
VOID
|
||
VideoPortWritePortUchar(
|
||
IN PUCHAR Port,
|
||
IN UCHAR Value
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWritePortUchar writes a byte to the specified port address. It
|
||
requires a logical port address obtained from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Value - Specifies a byte to be written to the port.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
pVideoDebugPrint((3,"VideoPortWritePortUchar %x %x\n", Port, Value));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_PORT_UCHAR(Port, Value);
|
||
|
||
} // VideoPortWritePortUchar()
|
||
|
||
VOID
|
||
VideoPortWritePortUshort(
|
||
IN PUSHORT Port,
|
||
IN USHORT Value
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWritePortUshort writes a word to the specified port address. It
|
||
requires a logical port address obtained from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Value - Specifies a word to be written to the port.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
pVideoDebugPrint((3,"VideoPortWritePortUhort %x %x\n", Port, Value));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_PORT_USHORT(Port, Value);
|
||
|
||
} // VideoPortWritePortUshort()
|
||
|
||
VOID
|
||
VideoPortWritePortUlong(
|
||
IN PULONG Port,
|
||
IN ULONG Value
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWritePortUlong writes a double word to the specified port address.
|
||
It requires a logical port address obtained from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Value - Specifies a double word to be written to the port.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
pVideoDebugPrint((3,"VideoPortWritePortUlong %x %x\n", Port, Value));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_PORT_ULONG(Port, Value);
|
||
|
||
} // VideoPortWritePortUlong()
|
||
|
||
VOID
|
||
VideoPortWritePortBufferUchar(
|
||
IN PUCHAR Port,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWritePortBufferUchar writes a number of bytes to a
|
||
specific port. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Buffer - Points to an array of bytes to be written.
|
||
|
||
Count - Specifies the number of bytes to be written to the buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
pVideoDebugPrint((3,"VideoPortWritePortBufferUchar %x \n", Port));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count);
|
||
|
||
} // VideoPortWritePortBufferUchar()
|
||
|
||
VOID
|
||
VideoPortWritePortBufferUshort(
|
||
IN PUSHORT Port,
|
||
IN PUSHORT Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWritePortBufferUshort writes a number of words to a
|
||
specific port. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Buffer - Points to an array of words to be written.
|
||
|
||
Count - Specifies the number of words to be written to the buffer.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
pVideoDebugPrint((3,"VideoPortWritePortBufferUshort %x \n", Port));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count);
|
||
|
||
} // VideoPortWritePortBufferUshort()
|
||
|
||
VOID
|
||
VideoPortWritePortBufferUlong(
|
||
IN PULONG Port,
|
||
IN PULONG Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWritePortBufferUlong writes a number of double words to a
|
||
specific port. It requires a logical port address obtained from
|
||
VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Port - Specifies the port address.
|
||
|
||
Buffer - Points to an array of double word to be written.
|
||
|
||
Count - Specifies the number of double words to be written to the buffer.
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
pVideoDebugPrint((3,"VideoPortWriteBufferUlong %x \n", Port));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count);
|
||
|
||
} // VideoPortWritePortBufferUlong()
|
||
|
||
VOID
|
||
VideoPortWriteRegisterUchar(
|
||
IN PUCHAR Register,
|
||
IN UCHAR Value
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWriteRegisterUchar writes a byte to the specified
|
||
register address. It requires a logical port address obtained
|
||
from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Register - Specifies the register address.
|
||
|
||
Value - Specifies a byte to be written to the register.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
pVideoDebugPrint((3,"VideoPortWritePortRegisterUchar %x \n", Register));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_REGISTER_UCHAR(Register, Value);
|
||
|
||
} // VideoPortWriteRegisterUchar()
|
||
|
||
VOID
|
||
VideoPortWriteRegisterUshort(
|
||
IN PUSHORT Register,
|
||
IN USHORT Value
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWriteRegisterUshort writes a word to the specified
|
||
register address. It requires a logical port address obtained
|
||
from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Register - Specifies the register address.
|
||
|
||
Value - Specifies a word to be written to the register.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
pVideoDebugPrint((3,"VideoPortWritePortRegisterUshort %x \n", Register));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_REGISTER_USHORT(Register, Value);
|
||
|
||
} // VideoPortWriteRegisterUshort()
|
||
|
||
VOID
|
||
VideoPortWriteRegisterUlong(
|
||
IN PULONG Register,
|
||
IN ULONG Value
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortWriteRegisterUlong writes a double word to the
|
||
specified register address. It requires a logical port
|
||
address obtained from VideoPortGetDeviceBase.
|
||
|
||
Arguments:
|
||
|
||
Register - Specifies the register address.
|
||
|
||
Value - Specifies a double word to be written to the register.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
pVideoDebugPrint((3,"VideoPortWritePortRegisterUlong %x \n", Register));
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_REGISTER_ULONG(Register, Value);
|
||
|
||
} // VideoPortWriteRegisterUlong()
|
||
|
||
|
||
VOID
|
||
VideoPortWriteRegisterBufferUchar(
|
||
IN PUCHAR Register,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Write a buffer of unsigned bytes from the specified register address.
|
||
|
||
Arguments:
|
||
|
||
Register - Supplies a pointer to the port address.
|
||
Buffer - Supplies a pointer to the data buffer area.
|
||
Count - The count of items to move.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
|
||
|
||
}
|
||
|
||
VOID
|
||
VideoPortWriteRegisterBufferUshort(
|
||
IN PUSHORT Register,
|
||
IN PUSHORT Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Write a buffer of unsigned shorts from the specified register address.
|
||
|
||
Arguments:
|
||
|
||
Register - Supplies a pointer to the port address.
|
||
Buffer - Supplies a pointer to the data buffer area.
|
||
Count - The count of items to move.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
|
||
|
||
}
|
||
|
||
VOID
|
||
VideoPortWriteRegisterBufferUlong(
|
||
IN PULONG Register,
|
||
IN PULONG Buffer,
|
||
IN ULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Write a buffer of unsigned longs from the specified register address.
|
||
|
||
Arguments:
|
||
|
||
Register - Supplies a pointer to the port address.
|
||
Buffer - Supplies a pointer to the data buffer area.
|
||
Count - The count of items to move.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
IS_ACCESS_RANGES_DEFINED()
|
||
|
||
WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
|
||
|
||
}
|
||
|
||
#endif // (DBG || (!defined(_X86_) && !defined(_ALPHA_)))
|
||
|
||
//
|
||
//VOID
|
||
//VideoPortZeroMemory(
|
||
// IN PVOID Destination,
|
||
// IN ULONG Length
|
||
// )
|
||
//
|
||
//Forwarded to RtlZeroMemory(Destination,Length);
|
||
//
|
||
|
||
PVOID
|
||
VideoPortGetAssociatedDeviceExtension(
|
||
IN PVOID DeviceObject
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will return the HwDeviceExtension for the parent of the
|
||
given device object.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The child device object (PDO).
|
||
|
||
Notes:
|
||
|
||
This function is useful if you want to get the parent device extension
|
||
for a child device object. For example this is useful with I2C.
|
||
|
||
--*/
|
||
|
||
{
|
||
PFDO_EXTENSION DeviceExtension;
|
||
|
||
DeviceExtension = (PFDO_EXTENSION)((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
|
||
|
||
return (PVOID) DeviceExtension->HwDeviceExtension;
|
||
}
|
||
|
||
VOID
|
||
VideoPortAcquireDeviceLock(
|
||
IN PVOID HwDeviceExtension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine acquires the per device lock maintained by the videoprt.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the hardware device extension.
|
||
|
||
--*/
|
||
|
||
{
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
ACQUIRE_DEVICE_LOCK(fdoExtension);
|
||
}
|
||
|
||
VOID
|
||
VideoPortReleaseDeviceLock(
|
||
IN PVOID HwDeviceExtension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine releases the per device lock maintained by the videoprt.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the hardware device extension.
|
||
|
||
--*/
|
||
|
||
{
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
RELEASE_DEVICE_LOCK(fdoExtension);
|
||
}
|
||
|
||
PVOID
|
||
VpGetProcAddress(
|
||
IN PVOID HwDeviceExtension,
|
||
IN PUCHAR FunctionName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allows a video miniport to get access to VideoPort
|
||
functions without linking to them directly. This will allow an NT 5.0
|
||
miniport to take advantage of NT 5.0 features while running on NT 5.0,
|
||
but still retain the ability to load on NT 4.0.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the hardware device extension.
|
||
|
||
FunctionName - pointer to a zero terminated ascii string which contains
|
||
the function name we are looking for.
|
||
|
||
Returns:
|
||
|
||
Pointer to the given function if it exists.
|
||
NULL otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
PPROC_ADDRESS ProcAddress = VideoPortEntryPoints;
|
||
|
||
//
|
||
// Since the list of exported functions is small, and this routine
|
||
// will not be called often we can get away with a linear search.
|
||
//
|
||
|
||
while (ProcAddress->FunctionName) {
|
||
|
||
if (strcmp(ProcAddress->FunctionName, FunctionName) == 0) {
|
||
return ProcAddress->FunctionAddress;
|
||
}
|
||
|
||
ProcAddress++;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
NTSTATUS
|
||
VpGetBusInterface(
|
||
PFDO_EXTENSION FdoExtension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Send a QueryInterface Irp to our parent to retrieve
|
||
the BUS_INTERFACE_STANDARD.
|
||
|
||
Returns:
|
||
|
||
NT_STATUS code
|
||
|
||
--*/
|
||
|
||
{
|
||
KEVENT Event;
|
||
PIRP QueryIrp = NULL;
|
||
IO_STATUS_BLOCK IoStatusBlock;
|
||
PIO_STACK_LOCATION NextStack;
|
||
NTSTATUS Status;
|
||
|
||
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
||
|
||
QueryIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
|
||
FdoExtension->AttachedDeviceObject,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
&Event,
|
||
&IoStatusBlock);
|
||
|
||
if (QueryIrp == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
QueryIrp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
|
||
|
||
NextStack = IoGetNextIrpStackLocation(QueryIrp);
|
||
|
||
//
|
||
// Set up for a QueryInterface Irp.
|
||
//
|
||
|
||
NextStack->MajorFunction = IRP_MJ_PNP;
|
||
NextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
||
|
||
NextStack->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD;
|
||
NextStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
|
||
NextStack->Parameters.QueryInterface.Version = 1;
|
||
NextStack->Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->BusInterface;
|
||
NextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
||
|
||
FdoExtension->BusInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
|
||
FdoExtension->BusInterface.Version = 1;
|
||
|
||
Status = IoCallDriver(FdoExtension->AttachedDeviceObject, QueryIrp);
|
||
|
||
if (Status == STATUS_PENDING) {
|
||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||
Status = IoStatusBlock.Status;
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// ALL the functions to perform interlocked operations are forwarded on free
|
||
// builds on x86 and ALPHA to the appropriate kernel function.
|
||
// This saves time and memory
|
||
//
|
||
|
||
#if !defined(_X86_)
|
||
|
||
LONG
|
||
FASTCALL
|
||
VideoPortInterlockedExchange(
|
||
IN OUT PLONG Target,
|
||
IN LONG Value
|
||
)
|
||
|
||
{
|
||
return InterlockedExchange(Target, Value);
|
||
}
|
||
|
||
LONG
|
||
FASTCALL
|
||
VideoPortInterlockedIncrement(
|
||
IN PLONG Addend
|
||
)
|
||
|
||
{
|
||
return InterlockedIncrement(Addend);
|
||
}
|
||
|
||
LONG
|
||
FASTCALL
|
||
VideoPortInterlockedDecrement(
|
||
IN PLONG Addend
|
||
)
|
||
|
||
{
|
||
return InterlockedDecrement(Addend);
|
||
}
|
||
|
||
#endif // !defined(_X86_)
|
||
|
||
VP_STATUS
|
||
VideoPortGetVgaStatus(
|
||
PVOID HwDeviceExtension,
|
||
OUT PULONG VgaStatus
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
VideoPortGetVgaStatus detect if the calling device is decoding
|
||
Vga IO address
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Points to the miniport driver's device extension
|
||
VgaStatus - Points to the the result
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR if the function completes successfully.
|
||
|
||
ERROR_INVALID_FUNCTION if it is a non-PCI device
|
||
|
||
--*/
|
||
{
|
||
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
//
|
||
// We can not handle legacy devices
|
||
//
|
||
|
||
if (fdoExtension->AdapterInterfaceType != PCIBus) {
|
||
|
||
*VgaStatus = 0;
|
||
|
||
return ERROR_INVALID_FUNCTION;
|
||
}
|
||
else {
|
||
|
||
*VgaStatus = pVideoPortGetVgaStatusPci( HwDeviceExtension );
|
||
return (NO_ERROR);
|
||
|
||
}
|
||
}
|
||
|
||
#define VGA_STATUS_REGISTER1 0x3DA
|
||
|
||
ULONG
|
||
pVideoPortGetVgaStatusPci(
|
||
PVOID HwDeviceExtension
|
||
)
|
||
|
||
{
|
||
|
||
USHORT Command;
|
||
PCI_COMMON_CONFIG ConfigSpace;
|
||
PHYSICAL_ADDRESS PhysicalAddress;
|
||
PUCHAR BaseReg;
|
||
ULONG VgaEnable;
|
||
|
||
//
|
||
// assume VGA is disabled
|
||
//
|
||
|
||
VgaEnable = 0;
|
||
|
||
//
|
||
// Get the PCI config for this device
|
||
//
|
||
|
||
VideoPortGetBusData( HwDeviceExtension,
|
||
PCIConfiguration,
|
||
0,
|
||
&ConfigSpace,
|
||
0,
|
||
PCI_COMMON_HDR_LENGTH);
|
||
|
||
|
||
if( !(ConfigSpace.Command & PCI_ENABLE_IO_SPACE) ) {
|
||
|
||
return VgaEnable;
|
||
|
||
}
|
||
|
||
if (((ConfigSpace.BaseClass == PCI_CLASS_PRE_20) &&
|
||
(ConfigSpace.SubClass == PCI_SUBCLASS_PRE_20_VGA)) ||
|
||
((ConfigSpace.BaseClass == PCI_CLASS_DISPLAY_CTLR) &&
|
||
(ConfigSpace.SubClass == PCI_SUBCLASS_VID_VGA_CTLR))) {
|
||
|
||
|
||
//
|
||
// Map the VGA registers we are going to use.
|
||
//
|
||
|
||
PhysicalAddress.HighPart = 0;
|
||
PhysicalAddress.LowPart = VGA_STATUS_REGISTER1;
|
||
|
||
BaseReg = VideoPortGetDeviceBase(HwDeviceExtension,
|
||
PhysicalAddress,
|
||
1,
|
||
VIDEO_MEMORY_SPACE_IO);
|
||
|
||
if (BaseReg) {
|
||
|
||
//
|
||
// If we got here the PCI config space for our device indicates
|
||
// we are the VGA, and we were able to map the VGA resources.
|
||
//
|
||
|
||
VgaEnable = DEVICE_VGA_ENABLED;
|
||
|
||
VideoPortFreeDeviceBase(HwDeviceExtension, BaseReg);
|
||
}
|
||
}
|
||
|
||
return VgaEnable;
|
||
}
|
||
|
||
VOID
|
||
pVideoPortDpcDispatcher(
|
||
IN PKDPC Dpc,
|
||
IN PVOID HwDeviceExtension,
|
||
IN PMINIPORT_DPC_ROUTINE DpcRoutine,
|
||
IN PVOID Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles DPCs and forwards them to the miniport callback
|
||
routine.
|
||
|
||
Arguments:
|
||
|
||
Dpc - The DPC which is executing.
|
||
|
||
HwDeviceExtension - The HwDeviceExtension for the device which scheduled
|
||
the DPC.
|
||
|
||
DpcRoutine - The callback in the miniport which needs to be called.
|
||
|
||
Context - The miniport supplied context.
|
||
|
||
Returns:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
DpcRoutine(HwDeviceExtension, Context);
|
||
}
|
||
|
||
BOOLEAN
|
||
VideoPortQueueDpc(
|
||
IN PVOID HwDeviceExtension,
|
||
IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
|
||
IN PVOID Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allows a miniport driver to queue a DPC.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - The HwDeviceExtension for the miniport.
|
||
|
||
CallbackRoutine - The entry point within the miniport to call when the DPC
|
||
is scheduled.
|
||
|
||
Context - A miniport supplies context which will be passed to the
|
||
CallbackRoutine.
|
||
|
||
Returns:
|
||
|
||
TRUE if successful,
|
||
FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
|
||
|
||
return KeInsertQueueDpc(&fdoExtension->Dpc, CallbackRoutine, Context);
|
||
}
|