windows-nt/Source/XPSP1/NT/drivers/video/ms/vga/mini/oldvga.c

1177 lines
28 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
in DRIVER_ENTRY
}
DeviceExtension->CommandPhase = ScrIdle;
NTSTATUS
ScreenInitializeDevice(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to the device object for this driver.
Return Value:
The function value is the status of the operation.
--*/
{
NTSTATUS Status;
//
// determine hardware configuration.
//
UCHAR videoType; // possible VGA video type
KIRQL OldIrql;
UCHAR Color = TRUE; // assume color adapter present
//
// Start by assuming there is no adapter
//
DeviceExtension->VideoHardware.fVideoType = VDHERROR_NO_ADAPTER;
//
// Determine which adapter is present by testing the presence of memory.
// A0000 isn't accessible because EGA and VGA come up in character mode.
// put it in graphics mode and then test for memory at A0000.
//
KeRaiseIrql(POWER_LEVEL,
&OldIrql);
EnableA0000();
KeLowerIrql(OldIrql);
if (MemoryPresent(MEM_EGA_OR_VGA)) {
//
// A0000 is present so we must either have an EGA or a VGA.
// We must now determine which one it is.
//
videoType = VGA_COLOR;
if (videoType == VGA_CANNOT_DETERMINE) {
} else { // We are in VGA mode
//
// determine and record VGA information; always 256K
//
DeviceExtension->VideoHardware.memory = 256L * 1024L;
switch (videoType) {
case VGA_COLOR:
DeviceExtension->VideoHardware.display = Color8512_8513;
DeviceExtension->VideoHardware.popupMode = ModeIndex_VGA3p;
DeviceExtension->VideoHardware.fVideoType ^= VGC_BIT;
break;
case VGA_MONO:
DeviceExtension->VideoHardware.display = Color8512_8513;
DeviceExtension->VideoHardware.popupMode = ModeIndex_VGA3p;
DeviceExtension->VideoHardware.fVideoType ^= VGC_BIT;
break;
case VGA_NODISPLAY:
DeviceExtension->VideoHardware.display = NoDisplay;
DeviceExtension->VideoHardware.popupMode = ModeIndex_VGA3p;
DeviceExtension->VideoHardware.fVideoType = NODISPLAY_BIT;
break;
}
}
}
KeRaiseIrql(POWER_LEVEL,
&OldIrql);
DisableA0000(Color);
KeLowerIrql(OldIrql);
if (DeviceExtension->VideoHardware.fVideoType == NODISPLAY_BIT) {
return STATUS_NO_SUCH_DEVICE;
}
//
// set up the ROM font addresses
//
InitializeFonts(DeviceExtension);
//
// set the mode.
//
Status = PrepareForSetMode(DeviceExtension,
DeviceExtension->VideoHardware.popupMode);
if (!NT_SUCCESS(Status)) {
return Status;
}
KeRaiseIrql(POWER_LEVEL,
&OldIrql);
SetHWMode(DeviceExtension,
DeviceExtension->VideoHardware.popupMode,
TRUE);
//
// Setting up the cursor position and initializing the CLUT only needs
// to be done for VGA mode.
//
//
// set up the cursor position and type
//
{
SCREEN_CURSOR_POSITION CursorPosition;
SCREEN_CURSOR_TYPE CursorType;
CursorPosition.Column = 0;
CursorPosition.Row = 0;
SetCursorPosition(DeviceExtension,
&CursorPosition);
CursorType.TopScanLine = (USHORT)
(Fonts[DeviceExtension->RomFontIndex].PelRows-2);
CursorType.BottomScanLine = 31;
CursorType.CursorVisible = TRUE;
SetCursorType(DeviceExtension,
&CursorType);
}
//
// initialize the CLUT.
//
SetColorLookup(DeviceExtension,
(PSCREEN_CLUT) &InitialClutVGA,
TRUE);
//
// initialize the palette registers.
//
SetPaletteReg(DeviceExtension,
(PSCREEN_PALETTE_DATA) &InitialPaletteVGA,
TRUE);
KeLowerIrql(OldIrql);
return STATUS_SUCCESS;
}
BOOLEAN
MemoryPresent(
IN ULONG Address
)
/*++
Routine Description:
This routine returns TRUE if the specified memory is present. It
maps a view of the requested address, reads the original ulong, writes
a different one, reads it to make sure its the written value, then
restores the original value.
Arguments:
Address - Physical address to check
Return Value:
TRUE if specified memory is present, FALSE if not.
--*/
{
BOOLEAN GoodMemory = FALSE; // assume no memory at location
volatile PULONG VideoMemory;
ULONG TestValue; // memory read/write test value
ULONG OriginalValue; // original value at tested location
PVOID Base;
Base = MmMapIoSpace((PHYSICAL_ADDRESS) Address,
sizeof (ULONG),
FALSE);
//
// Read a ulong from the address and save it. write
// a different ulong to the address. read from the address and see if
// it matches the written ulong.
//
VideoMemory = (PULONG) Base;
TestValue = 0xBBBBBBBB;
if ((OriginalValue = *VideoMemory) == 0xBBBBBBBB) {
TestValue >>= 1;
}
*VideoMemory = TestValue; // write out a test value
if (GoodMemory = (BOOLEAN) (*VideoMemory == TestValue) ) {
*VideoMemory = OriginalValue; // restore value
}
MmUnmapIoSpace(Base,
sizeof (ULONG));
return GoodMemory;
}
VOID
InitializeFonts(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine determines the addresses of the ROM fonts.
Arguments:
DeviceExtension - pointer to device extension for this driver
Return Value:
none
--*/
{
PHYSICAL_ADDRESS PVB;
PUCHAR RomPtr;
ULONG RomFontLen,ROMSrchLen;
ULONG i;
//
// Search through ROM to find 8x8, 8x14, 8x16, 9x14, and 9x16 fonts
// ROM fonts are located at physical addresses:
// C0000 - EGA and PS/2 Adapter
// E0000 - VGA
//
for (PVB = 0xE0000, RomFontLen = 0xFFFF, ROMSrchLen = 0xFFF0;
PVB >= 0xC0000;
PVB -= 0x20000, RomFontLen -= 0x8000, ROMSrchLen = 0x7FF0 ) {
RomPtr = MmMapIoSpace(PVB, RomFontLen, FALSE);
//
// Locate 8x8 ROM font on EGA and VGA
//
for (i = 0; i < ROMSrchLen; i++) {
while ( (i < ROMSrchLen) && (RomPtr[i] != (UCHAR)0x7E) ) {
i++;
}
if ( i < ROMSrchLen) {
if ( (RomPtr[i+1] == (UCHAR)0x81) &&
(RomPtr[i+2] == (UCHAR)0xA5) &&
(RomPtr[i+3] == (UCHAR)0x81) ) {
if (!Fonts[ROM_FONT_8x8].PVB && RomPtr[i+4] ==
(UCHAR)0xBD) {
Fonts[ROM_FONT_8x8].PVB = PVB + i - 8;
} else {
//
// Locate 8x14 ROM font on EGA, VGA, and PS/2 adapter only
//
if ( (RomPtr[i+4] == (UCHAR)0x81) &&
(RomPtr[i+5] == (UCHAR)0xBD) &&
(RomPtr[i+6] == (UCHAR)0x99) &&
(RomPtr[i+7] == (UCHAR)0x81) ) {
// e3f40
if (!Fonts[ROM_FONT_8x14].PVB &&
RomPtr[i+8] != (UCHAR)0x81) {
Fonts[ROM_FONT_8x14].PVB = PVB + i- 16;
} else {
//
// Locate 8x16 ROM font on VGA, and PS/2 adapter only
//
// e3e04
if ( !Fonts[ROM_FONT_8x16].PVB &&
RomPtr[i+8] == (UCHAR)0x81 ) {
Fonts[ROM_FONT_8x16].PVB = PVB + i - 18;
}
}
} // if ( (RomPtr[i+4] == (UCHAR)0x81) &&
} // if (!Fonts[ROM_FONT_8x8].PVB && RomPtr[i+4]
} // if ( (RomPtr[i+1] == (UCHAR)0x81) &&
} // if ( i < ROMSrchLen)
} // end for loop Locate 8x8, 8x14, 8x16
//
// Locate 9x14 ROM font on EGA, VGA, and PS/2 adapter only
//
for ( i = 0; i < ROMSrchLen; i++ ) {
while ( (i < ROMSrchLen) && (RomPtr[i] != (UCHAR)0x1D) ) {
i++;
}
if ( i < ROMSrchLen) {
if ( ( RomPtr[i+1] == (UCHAR)0x00 ) &&
( RomPtr[i+2] == (UCHAR)0x00 ) &&
( RomPtr[i+3] == (UCHAR)0x00 ) &&
( RomPtr[i+4] == (UCHAR)0x00 ) ) {
if ( !Fonts[ROM_FONT_9x14].PVB &&
( RomPtr[i+5] == (UCHAR)0x24 ) &&
( RomPtr[i+6] == (UCHAR)0x66 ) ) {
Fonts[ROM_FONT_9x14].PVB = PVB + i;
}
//
// Locate 9x16 ROM font on VGA, and PS/2 adapter only
//
if (!Fonts[ROM_FONT_9x16].PVB &&
(RomPtr[i+5] == (UCHAR)0x00) &&
(RomPtr[i+6] == (UCHAR)0x24) ) {
Fonts[ROM_FONT_9x16].PVB = PVB + i;
}
}
}
} /* Locate 9x14, 9x16 */
MmUnmapIoSpace(RomPtr,RomFontLen);
} // Search next ROM area for fonts */
if (!Fonts[ROM_FONT_8x8].PVB)
Dprint(1, ("Fonts[ROM_FONT_8x8] not found\n"));
if (!Fonts[ROM_FONT_8x14].PVB)
Dprint(1, ("Fonts[ROM_FONT_8x14] not found \n"));
if (!Fonts[ROM_FONT_8x16].PVB)
Dprint(1, ("Fonts[ROM_FONT_8x16] not found \n"));
if (!Fonts[ROM_FONT_9x14].PVB)
Dprint(1, ("Fonts[ROM_FONT_9x14] not found \n"));
if (!Fonts[ROM_FONT_9x16].PVB)
Dprint(1, ("Fonts[ROM_FONT_9x16] not found \n"));
//
// we happen to know that the 8x8 font is loaded during boot. we can't
// call SetFont at this point because it requires data initialized by
// SetMode. But SetMode requires data initialized by SetFont. so we
// just set up RomFontIndex here manually.
//
DeviceExtension->RomFontIndex = 1;
}
NTSTATUS
ScreenDispatch(
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
KIRQL OldIrql;
PDEVICE_EXTENSION DeviceExtension;
BOOLEAN PowerFailed = FALSE;
PVOID SystemBuffer;
case IRP_MJ_CLOSE:
Dprint(2, ("VgaDispatch - CLose\n"));
Status = ZwUnmapViewOfSection(NtCurrentProcess(),
DeviceExtension->RealFrameBase);
if (NT_SUCCESS(Status)) {
ZwClose(DeviceExtension->FrameSection);
}
break;
case IOCTL_SCR_QUERY_FRAME_BUFFER:
Dprint(2, ("VgaDispatch - QueryFrameBuffer\n"));
//
// check for adequate buffer length
//
if (RequestPacket->OutputBufferLength <
sizeof(SCREEN_FRAME_BUFFER_INFO)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
//
// everything's ok, return the info.
//
((PSCREEN_FRAME_BUFFER_INFO) SystemBuffer)->FrameBase =
DeviceExtension->FrameBase;
((PSCREEN_FRAME_BUFFER_INFO) SystemBuffer)->FrameLength =
DeviceExtension->FrameLength;
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(SCREEN_FRAME_BUFFER_INFO);
}
break;
case IOCTL_SCR_QUERY_AVAIL_MODES:
Dprint(2, ("VgaDispatch - QueryAvailableModes\n"));
Status = GetAvailableModes(DeviceExtension,
RequestPacket->OutputBufferLength,
SystemBuffer,
&Irp->IoStatus.Information);
break;
case IOCTL_SCR_QUERY_NUM_AVAIL_MODES:
Dprint(2, ("VgaDispatch - QueryNumAvailableModes\n"));
if (RequestPacket->OutputBufferLength <
sizeof(SCREEN_NUM_MODES)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Status = GetNumberOfAvailableModes(DeviceExtension,
&(((PSCREEN_NUM_MODES)SystemBuffer)->NumModes));
Irp->IoStatus.Information = sizeof(SCREEN_NUM_MODES);
}
break;
case IOCTL_SCR_QUERY_CURRENT_MODE:
Dprint(2, ("VgaDispatch - QueryCurrentMode\n"));
//
// Statistics compilation
//
ScreenIoctlStats.QueryCurrentMode++;
if (RequestPacket->OutputBufferLength <
sizeof(SCREEN_MODE_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Status = GetCurrentMode(DeviceExtension,
RequestPacket->OutputBufferLength,
SystemBuffer);
Irp->IoStatus.Information = sizeof(SCREEN_MODE_INFORMATION);
}
break;
case IOCTL_SCR_SET_CURRENT_MODE:
Dprint(2, ("VgaDispatch - SetCurrentModes\n"));
if (RequestPacket->InputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
//
// validate mode and set up device extension variables
//
Status = PrepareForSetMode(DeviceExtension,
*((PULONG) SystemBuffer));
if (NT_SUCCESS(Status)) {
//
// unmap old frame buffer and set up new one.
//
Status = UpdateFrameBuffer(DeviceExtension,
TRUE,
*((PULONG) SystemBuffer));
if (NT_SUCCESS(Status)) {
//
// update hardware
//
SetHWMode(DeviceExtension,
*((PULONG) SystemBuffer),
TRUE);
}
}
}
break;
case IOCTL_SCR_QUERY_AVAIL_FONTS:
Dprint(2, ("VgaDispatch - QueryAvailableFont\n"));
if (DeviceExtension->CurrentMode->fbType & SCREEN_MODE_GRAPHICS) {
//
// Text mode only
//
Status = STATUS_INVALID_PARAMETER;
} else {
Status = GetAvailableFonts(DeviceExtension,
RequestPacket->OutputBufferLength,
SystemBuffer,
&Irp->IoStatus.Information);
}
break;
case IOCTL_SCR_QUERY_NUM_AVAIL_FONTS:
Dprint(2, ("VgaDispatch - QueryNumAvailableFonts\n"));
if (RequestPacket->OutputBufferLength <
sizeof(SCREEN_NUM_FONTS)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if (DeviceExtension->CurrentMode->fbType &
SCREEN_MODE_GRAPHICS) { // Text mode only
Status = STATUS_INVALID_PARAMETER;
} else {
Status = GetNumberOfAvailableFonts(DeviceExtension,
&((PSCREEN_NUM_FONTS)SystemBuffer)->NumFonts);
Irp->IoStatus.Information = sizeof(SCREEN_NUM_FONTS);
}
}
break;
case IOCTL_SCR_QUERY_CURRENT_FONT:
Dprint(2, ("VgaDispatch - QueryCurrentFont\n"));
if (RequestPacket->OutputBufferLength <
sizeof(SCREEN_FONT_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if (DeviceExtension->CurrentMode->fbType &
SCREEN_MODE_GRAPHICS) { // Text mode only
Status = STATUS_INVALID_PARAMETER;
} else {
Status = GetCurrentFont(DeviceExtension,
SystemBuffer);
Irp->IoStatus.Information =
sizeof(SCREEN_FONT_INFORMATION);
}
}
break;
case IOCTL_SCR_SET_CURRENT_FONT:
Dprint(2, ("VgaDispatch - SetCurrentFont\n"));
if (RequestPacket->InputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if ( ((*(PULONG)SystemBuffer) > ROM_FONTS_VGA) ||
((*(PULONG)SystemBuffer) == 0) ||
(DeviceExtension->CurrentMode->fbType &
SCREEN_MODE_GRAPHICS)) { // Text mode only
Status = STATUS_INVALID_PARAMETER;
} else {
SCREEN_SET_FONT_INFORMATION FontInformation;
Status = SetFontSetUp(DeviceExtension,
*(PULONG)SystemBuffer,
&FontInformation);
SetFont(DeviceExtension,
FontInformation);
Status = SetFontCleanUp(*(PULONG)SystemBuffer,
&FontInformation);
}
}
break;
case IOCTL_SCR_QUERY_CURSOR_POSITION:
Dprint(2, ("VgaDispatch - QueryCursorPosition\n"));
if (RequestPacket->OutputBufferLength <
sizeof(SCREEN_CURSOR_POSITION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if (DeviceExtension->CurrentMode->fbType &
SCREEN_MODE_GRAPHICS) { // Text mode only
Status = STATUS_INVALID_PARAMETER;
} else {
Status = GetCursorPosition(DeviceExtension,
SystemBuffer);
Irp->IoStatus.Information =
sizeof(SCREEN_CURSOR_POSITION);
}
}
break;
case IOCTL_SCR_SET_CURSOR_POSITION:
Dprint(2, ("VgaDispatch - SetCursorPosition\n"));
if (RequestPacket->InputBufferLength <
sizeof(SCREEN_CURSOR_POSITION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if ((DeviceExtension->CurrentMode->fbType &
SCREEN_MODE_GRAPHICS) || // Text mode only
(!CheckCursorPosition(SystemBuffer,
DeviceExtension))) {
Status = STATUS_INVALID_PARAMETER;
} else {
Status = STATUS_SUCCESS;
???? SetCursorPosition(DeviceExtension,
(PSCREEN_CURSOR_POSITION) SystemBuffer);
}
}
break;
case IOCTL_SCR_QUERY_CURSOR_TYPE:
Dprint(2, ("VgaDispatch - QueryCursorType\n"));
if (RequestPacket->OutputBufferLength <
sizeof(SCREEN_CURSOR_TYPE)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if (DeviceExtension->CurrentMode->fbType &
SCREEN_MODE_GRAPHICS) { // Text mode only
Status = STATUS_INVALID_PARAMETER;
} else {
Status = GetCursorType(DeviceExtension,
SystemBuffer);
Irp->IoStatus.Information = sizeof(SCREEN_CURSOR_TYPE);
}
}
break;
case IOCTL_SCR_SET_CURSOR_TYPE:
Dprint(2, ("VgaDispatch - SetCursorType\n"));
if (RequestPacket->InputBufferLength <
sizeof(SCREEN_CURSOR_TYPE)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if ((DeviceExtension->CurrentMode->fbType &
SCREEN_MODE_GRAPHICS) || // Text mode only
(!CheckCursorType(SystemBuffer,
DeviceExtension))) {
Status = STATUS_INVALID_PARAMETER;
} else {
Status = STATUS_SUCCESS;
SetCursorType(DeviceExtension,
(PSCREEN_CURSOR_TYPE) SystemBuffer);
}
}
break;
case IOCTL_SCR_SET_PALETTE_REGISTERS:
Dprint(2, ("VgaDispatch - SetPaletteRegs\n"));
Status = STATUS_SUCCESS;
if (RequestPacket->InputBufferLength <
(sizeof(SCREEN_PALETTE_DATA) + (sizeof(USHORT) *
(((PSCREEN_PALETTE_DATA)SystemBuffer)->NumEntries-1)))) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if ((((PSCREEN_PALETTE_DATA)SystemBuffer)->FirstEntry >
SCREEN_MAX_PALETTE_COLORS ) || // valid 1st entry
(((PSCREEN_PALETTE_DATA)SystemBuffer)->NumEntries ==
0) || // Non-zero amount
(((PSCREEN_PALETTE_DATA)SystemBuffer)->FirstEntry +
((PSCREEN_PALETTE_DATA)SystemBuffer)->NumEntries >
SCREEN_MAX_PALETTE_COLORS+1)) {
Status = STATUS_INVALID_PARAMETER;
} else {
SetPaletteReg(DeviceExtension,
(PSCREEN_PALETTE_DATA) SystemBuffer,
TRUE);
}
}
break;
case IOCTL_SCR_SET_COLOR_REGISTERS:
Dprint(2, ("VgaDispatch - SetColorRegs\n"));
Status = STATUS_SUCCESS;
if (RequestPacket->InputBufferLength <
(sizeof(SCREEN_CLUT) + (sizeof(ULONG) *
(((PSCREEN_CLUT)SystemBuffer)->NumEntries-1)))) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if ((((PSCREEN_CLUT)SystemBuffer)->NumEntries == 0) ||
(((PSCREEN_CLUT)SystemBuffer)->FirstEntry >
SCREEN_MAX_COLOR_REGISTERS) ||
(((PSCREEN_CLUT)SystemBuffer)->FirstEntry +
((PSCREEN_CLUT)SystemBuffer)->NumEntries >
SCREEN_MAX_COLOR_REGISTERS+1)) {
Status = STATUS_INVALID_PARAMETER;
} else {
SetColorLookup(DeviceExtension,
(PSCREEN_CLUT) SystemBuffer,
TRUE);
}
}
break;
}
break;
}
Irp->IoStatus.Status = Status;
if (PowerFailed) {
Status = STATUS_PENDING;
} else {
DeviceExtension->CommandPhase = ScrIdle; // this is only necessary
// for KeSynchronize ioctls
KeSetEvent(&DeviceExtension->Event,0,FALSE);
KeRaiseIrql( DISPATCH_LEVEL, &OldIrql );
IoCompleteRequest( Irp, IO_VIDEO_INCREMENT );
KeLowerIrql( OldIrql );
}
return Status;
}
BOOLEAN
ScreenResetDevice(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine resets the device after a powerfail. It sets the mode to
the current mode and the palette and color registers to what they were
before the powerfail.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Return Value:
For now simply return TRUE.
--*/
{
KIRQL OldIrql;
KeRaiseIrql(POWER_LEVEL,
&OldIrql);
#ifdef SCREEN_POWER_RECOVERY
if (DeviceExtension->ScreenPowerFailed == TRUE) {
KeLowerIrql( OldIrql );
return TRUE;
}
#endif // POWER_RECOVERY
SetHWMode(DeviceExtension,
DeviceExtension->ModeIndex,
FALSE);
if (!( DeviceExtension->CurrentMode->fbType & SCREEN_MODE_GRAPHICS ) ) {
SetHWFontRegs(DeviceExtension,
Fonts[DeviceExtension->RomFontIndex].PelRows);
SetCursorPosition(DeviceExtension,
&DeviceExtension->CursorPosition);
SetCursorType(DeviceExtension,
&DeviceExtension->CursorType);
}
SetColorLookup(DeviceExtension,
(PSCREEN_CLUT) &DeviceExtension->Clut,
FALSE);
SetPaletteReg(DeviceExtension,
(PSCREEN_PALETTE_DATA) &DeviceExtension->Palette,
FALSE);
KeLowerIrql(OldIrql);
return TRUE;
}
static
VOID
ScreenUnload (
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This routine is the unload routine for the screen disk device driver.
It performs no operation.
Arguments:
DriverObject - Supplies a pointer to the driver object that describes
this driver.
Return Value:
None.
--*/
{
DBG_UNREFERENCED_PARAMETER(DriverObject);
return;
}
#ifdef SCREEN_POWER_RECOVERY
VOID
ScreenPowerFail(
IN PKDPC Dpc,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is called when the power fails. It calls the routine
to reset the device and restart any operations that write to the
device. It also completes any operations that were pending due to
a powerfail.
Arguments:
Dpc - Pointer to DPC object.
DeviceObject - Pointer to the device object.
Irp - Pointer to Irp.
Context - Action to take in DCP.
Return Value:
None.
--*/
{
BOOLEAN PowerFailed;
PDEVICE_EXTENSION DeviceExtension;
KIRQL OldIrql;
DeviceExtension = DeviceObject->DeviceExtension;
//
// set ScreenPowerFailed to FALSE.
//
KeRaiseIrql(POWER_LEVEL,
&OldIrql);
DeviceExtension->ScreenPowerFailed = FALSE;
KeLowerIrql( OldIrql );
PowerFailed = KeSynchronizeExecution(
&DeviceExtension->ScreenInterruptObject,
ScreenPowerReset,
DeviceExtension);
if (PowerFailed == FALSE) {
DeviceExtension->CommandPhase = ScrIdle;
KeSetEvent(&DeviceExtension->Event,
0,
FALSE);
KeRaiseIrql(DISPATCH_LEVEL,
&OldIrql);
IoCompleteRequest(Irp,
IO_VIDEO_INCREMENT);
KeLowerIrql(OldIrql);
}
}
BOOLEAN
ScreenPowerReset(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine reinitializes the device after a powerfail and restarts
any operation that was writing to the device.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Return Value:
Whether the power failed during the reset.
--*/
{
PDEVICE_EXTENSION DeviceExtension;
BOOLEAN PowerFailed;
DeviceExtension = DeviceObject->DeviceExtension;
//
// reset the device. this sets the mode, palette regs, and CLUT to what
// they were before the powerfail.
//
PowerFailed = ScreenResetDevice(DeviceExtension);
if (PowerFailed) {
return TRUE;
}
//
// restart operation
//
if (DeviceExtension->CommandPhase != ScrIdle) {
return WriteToDevice(DeviceObject);
}
return FALSE;
}
#endif // POWER_RECOVERY