You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1004 lines
29 KiB
1004 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dispatch.c
|
|
|
|
Abstract:
|
|
|
|
IRP dispatching routines for the common AGPLIB library
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 10/25/1997
|
|
|
|
Revision History:
|
|
|
|
Elliot Shmukler (elliots) 3/24/1999 - Added support for "favored" memory
|
|
ranges for AGP physical memory allocation,
|
|
fixed some bugs.
|
|
|
|
--*/
|
|
#include "agplib.h"
|
|
|
|
//
|
|
// Two flavors of each dispatch routine, one for the target (AGP bridge) filter and
|
|
// one for the master (video card) filter.
|
|
//
|
|
|
|
NTSTATUS
|
|
AgpTargetDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PTARGET_EXTENSION Extension
|
|
);
|
|
|
|
NTSTATUS
|
|
AgpMasterDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
);
|
|
|
|
NTSTATUS
|
|
AgpTargetDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PTARGET_EXTENSION Extension
|
|
);
|
|
|
|
NTSTATUS
|
|
AgpMasterDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
);
|
|
|
|
NTSTATUS
|
|
AgpCancelMasterRemove(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
);
|
|
|
|
NTSTATUS
|
|
AgpMasterPowerUpCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
);
|
|
|
|
NTSTATUS
|
|
AgpTargetPowerUpCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PTARGET_EXTENSION Extension
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, AgpDispatchPnp)
|
|
#pragma alloc_text(PAGE, AgpDispatchDeviceControl)
|
|
#pragma alloc_text(PAGE, AgpDispatchWmi)
|
|
#pragma alloc_text(PAGE, AgpTargetDispatchPnp)
|
|
#pragma alloc_text(PAGE, AgpMasterDispatchPnp)
|
|
#pragma alloc_text(PAGE, AgpCancelMasterRemove)
|
|
#endif
|
|
|
|
|
|
|
|
NTSTATUS
|
|
AgpDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main dispatch routine for PNP irps sent to the AGP bus filter driver
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the AGP device object
|
|
|
|
Irp - Supplies the PNP Irp.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// We're deleted, fail the irp
|
|
//
|
|
if (Extension->Deleted == TRUE) {
|
|
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_DELETE_PENDING;
|
|
}
|
|
|
|
ASSERT(Extension->AttachedDevice != NULL);
|
|
|
|
if (Extension->Type == AgpTargetFilter) {
|
|
return(AgpTargetDispatchPnp(DeviceObject,
|
|
Irp,
|
|
DeviceObject->DeviceExtension));
|
|
} else {
|
|
ASSERT(Extension->Type == AgpMasterFilter);
|
|
return(AgpMasterDispatchPnp(DeviceObject,
|
|
Irp,
|
|
DeviceObject->DeviceExtension));
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main dispatch routine for power irps sent to the AGP bus filter driver
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the AGP device object
|
|
|
|
Irp - Supplies the power Irp.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// We're deleted, fail the irp
|
|
//
|
|
if (Extension->Deleted == TRUE) {
|
|
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
|
|
PoStartNextPowerIrp(Irp);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_DELETE_PENDING;
|
|
}
|
|
|
|
ASSERT(Extension->AttachedDevice != NULL);
|
|
|
|
if (Extension->Type == AgpTargetFilter) {
|
|
return(AgpTargetDispatchPower(DeviceObject,
|
|
Irp,
|
|
DeviceObject->DeviceExtension));
|
|
} else {
|
|
ASSERT(Extension->Type == AgpMasterFilter);
|
|
return(AgpMasterDispatchPower(DeviceObject,
|
|
Irp,
|
|
DeviceObject->DeviceExtension));
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpTargetDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PTARGET_EXTENSION Extension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dispatch routine for PNP irps sent to the AGP bus filter driver
|
|
attached to the target (AGP bridge) PDO.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the AGP target device object
|
|
|
|
Irp - Supplies the PNP Irp.
|
|
|
|
Extension - Supplies the AGP target device extension
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_NOT_SUPPORTED;
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
PAGED_CODE();
|
|
|
|
AGPLOG(AGP_IRPTRACE,
|
|
("AgpTargetDispatchPnp: IRP 0x%x\n", irpStack->MinorFunction));
|
|
|
|
switch (irpStack->MinorFunction) {
|
|
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
|
AGPLOG(AGP_NOISE,
|
|
("AgpTargetDispatchPnp: IRP_MN_FILTER_RESOURCE_REQUIREMENTS to %08lx\n",
|
|
DeviceObject));
|
|
|
|
Status = AgpFilterResourceRequirements(DeviceObject, Irp, Extension);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
AGPLOG(AGP_NOISE,
|
|
("AgpTargetDispatchPnp: IRP_MN_QUERY_RESOURCES to %08lx\n",
|
|
DeviceObject));
|
|
|
|
//
|
|
// We must handle this IRP on the way back so we can add the AGP
|
|
// resources on to it. Set a completion routine.
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
AgpQueryResources,
|
|
Extension,
|
|
TRUE,
|
|
FALSE,
|
|
FALSE);
|
|
Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
|
|
return Status ;
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
if (irpStack->Parameters.QueryDeviceRelations.Type == BusRelations) {
|
|
KEVENT event;
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
//
|
|
// We must handle this IRP on the way back so that we can attach
|
|
// a filter to any child PDOs of our PCI-PCI bridge.
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
AgpSetEventCompletion,
|
|
&event,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
|
|
|
|
//
|
|
// If we did things asynchronously then wait on our event
|
|
//
|
|
if (Status == STATUS_PENDING) {
|
|
|
|
//
|
|
// We do a KernelMode wait so that our stack where the
|
|
// event is doesn't get paged out!
|
|
//
|
|
KeWaitForSingleObject(&event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
Status = Irp->IoStatus.Status;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
Status = AgpAttachDeviceRelations(DeviceObject,
|
|
Irp,
|
|
Extension);
|
|
Irp->IoStatus.Status = Status;
|
|
}
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return Status;
|
|
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
//
|
|
// We need to hook this in order to filter out any AGP
|
|
// resources that have been added.
|
|
//
|
|
return(AgpStartTarget(Irp, Extension));
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
|
|
//
|
|
// We can always succeed this.
|
|
//
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
AgpDisableAperture(GET_AGP_CONTEXT(Extension));
|
|
|
|
//
|
|
// Pass the irp down
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
|
|
|
|
//
|
|
// Clean up and delete ourselves
|
|
//
|
|
AgpWmiDeRegistration(Extension);
|
|
Extension->CommonExtension.Deleted = TRUE;
|
|
IoDetachDevice(Extension->CommonExtension.AttachedDevice);
|
|
Extension->CommonExtension.AttachedDevice = NULL;
|
|
RELEASE_BUS_INTERFACE(Extension);
|
|
if (Extension->FavoredMemory.Ranges) {
|
|
ExFreePool(Extension->FavoredMemory.Ranges);
|
|
}
|
|
if (Extension->Resources) {
|
|
ExFreePool(Extension->Resources);
|
|
}
|
|
if (Extension->ResourcesTranslated) {
|
|
ExFreePool(Extension->ResourcesTranslated);
|
|
}
|
|
ExFreePool(Extension->Lock);;
|
|
IoDeleteDevice(DeviceObject);
|
|
return(Status);
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
AgpDisableAperture(GET_AGP_CONTEXT(Extension));
|
|
Status = STATUS_SUCCESS;
|
|
break; // forward irp down the stack
|
|
|
|
}
|
|
|
|
ASSERT(Status != STATUS_PENDING);
|
|
|
|
if (Status != STATUS_NOT_SUPPORTED) {
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_NOT_SUPPORTED)) {
|
|
|
|
//
|
|
// Forward IRP to PCI driver
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
|
|
|
|
} else {
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
|
|
return Status ;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpDispatchDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main dispatch routine for device control irps sent to the AGP bus filter driver
|
|
|
|
AGP currently does not support any device controls. So we just pass everything
|
|
down and hope the PDO knows what to do with it.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the AGP device object
|
|
|
|
Irp - Supplies the power Irp.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// We're deleted, fail the irp
|
|
//
|
|
if (Extension->Deleted == TRUE) {
|
|
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_DELETE_PENDING;
|
|
}
|
|
|
|
ASSERT(Extension->AttachedDevice != NULL);
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return(IoCallDriver(Extension->AttachedDevice, Irp));
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpDispatchWmi(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main dispatch routine for system control irps sent to the AGP bus filter
|
|
driver.
|
|
|
|
AGP currently does not support any WMI IRPs, so we just pass everything
|
|
down and hope the PDO knows what to do with it.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the AGP device object
|
|
|
|
Irp - Supplies the power Irp.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PCOMMON_EXTENSION Extension = DeviceObject->DeviceExtension;
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// We're deleted, fail the irp
|
|
//
|
|
if (Extension->Deleted == TRUE) {
|
|
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_DELETE_PENDING;
|
|
}
|
|
|
|
ASSERT(Extension->AttachedDevice != NULL);
|
|
|
|
//
|
|
// Return AGP info for target device
|
|
//
|
|
if (Extension->Type == AgpTargetFilter) {
|
|
return AgpSystemControl(DeviceObject, Irp);
|
|
}
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return(IoCallDriver(Extension->AttachedDevice, Irp));
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpTargetDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PTARGET_EXTENSION Extension
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
AGPLOG(AGP_IRPTRACE,
|
|
("AgpTargetDispatchPower: IRP 0x%x\n", irpStack->MinorFunction));
|
|
|
|
//
|
|
// All we keep track of are Dx states. PCI is responsible for mapping
|
|
// S-states into D states.
|
|
//
|
|
|
|
|
|
if ((irpStack->MinorFunction == IRP_MN_SET_POWER) &&
|
|
(irpStack->Parameters.Power.Type == DevicePowerState) &&
|
|
(irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
|
|
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// We need to reinitialize the target when this IRP has been completed
|
|
// by the lower drivers. Set up our completion handler to finish this.
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
AgpTargetPowerUpCompletion,
|
|
Extension,
|
|
TRUE,
|
|
FALSE,
|
|
FALSE);
|
|
|
|
IoMarkIrpPending(Irp);
|
|
PoStartNextPowerIrp(Irp);
|
|
Status = PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
|
|
return STATUS_PENDING;
|
|
}
|
|
//
|
|
// Just forward to target device
|
|
//
|
|
PoStartNextPowerIrp(Irp);
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return(PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpMasterDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dispatch routine for PNP irps sent to the AGP bus filter driver
|
|
attached to the device PDOs.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the AGP device object
|
|
|
|
Irp - Supplies the PNP Irp.
|
|
|
|
Extension - Supplies the AGP bridge device extension
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
|
PAGP_BUS_INTERFACE_STANDARD Interface;
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
AGPLOG(AGP_IRPTRACE,
|
|
("AgpMasterDispatchPnp: IRP 0x%x\n", irpStack->MinorFunction));
|
|
|
|
switch (irpStack->MinorFunction) {
|
|
case IRP_MN_QUERY_INTERFACE:
|
|
|
|
#if 0
|
|
AGPLOG(AGP_IRPTRACE,
|
|
("\tSize=0x%x, Version=%d\n"
|
|
"\tGUID=0x%08x-0x%04x-0x%04x-0x%02x-"
|
|
"0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x\n",
|
|
irpStack->Parameters.QueryInterface.Size,
|
|
irpStack->Parameters.QueryInterface.Version,
|
|
*(PULONG)irpStack->Parameters.QueryInterface.InterfaceType,
|
|
*((PUSHORT)irpStack->Parameters.QueryInterface.InterfaceType + 2),
|
|
*((PUSHORT)irpStack->Parameters.QueryInterface.InterfaceType + 3),
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 8),
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 9),
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 10),
|
|
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 11),
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 12),
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 13),
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 14),
|
|
*((PUCHAR)irpStack->Parameters.QueryInterface.InterfaceType + 15)));
|
|
|
|
#endif
|
|
|
|
//
|
|
// The only IRP we look for here is IRP_MN_QUERY_INTERFACE for
|
|
// GUID_AGP_BUS_INTERFACE_STANDARD.
|
|
//
|
|
if ((RtlEqualMemory(
|
|
irpStack->Parameters.QueryInterface.InterfaceType,
|
|
&GUID_AGP_BUS_INTERFACE_STANDARD,
|
|
sizeof(GUID))) &&
|
|
(((irpStack->Parameters.QueryInterface.Size >=
|
|
sizeof(AGP_BUS_INTERFACE_STANDARD)) &&
|
|
(irpStack->Parameters.QueryInterface.Version ==
|
|
AGP_BUS_INTERFACE_V2)) ||
|
|
((irpStack->Parameters.QueryInterface.Size >=
|
|
AGP_BUS_INTERFACE_V1_SIZE) &&
|
|
(irpStack->Parameters.QueryInterface.Version ==
|
|
AGP_BUS_INTERFACE_V1)))) {
|
|
|
|
Interface = (PAGP_BUS_INTERFACE_STANDARD)irpStack->Parameters.QueryInterface.Interface;
|
|
|
|
Interface->Version =
|
|
irpStack->Parameters.QueryInterface.Version;
|
|
Interface->AgpContext = Extension;
|
|
Interface->InterfaceReference = AgpInterfaceReference;
|
|
Interface->InterfaceDereference = AgpInterfaceDereference;
|
|
Interface->ReserveMemory = AgpInterfaceReserveMemory;
|
|
Interface->ReleaseMemory = AgpInterfaceReleaseMemory;
|
|
Interface->CommitMemory = AgpInterfaceCommitMemory;
|
|
Interface->FreeMemory = AgpInterfaceFreeMemory;
|
|
Interface->GetMappedPages = AgpInterfaceGetMappedPages;
|
|
|
|
if (Interface->Version < AGP_BUS_INTERFACE_V2) {
|
|
Interface->Size = AGP_BUS_INTERFACE_V1_SIZE;
|
|
} else {
|
|
Interface->Size = sizeof(AGP_BUS_INTERFACE_STANDARD);
|
|
Interface->SetRate = AgpInterfaceSetRate;
|
|
}
|
|
|
|
Interface->Capabilities = Extension->Capabilities;
|
|
|
|
//
|
|
// Complete the IRP successfully
|
|
//
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
// AGPLOG(AGP_IRPTRACE, ("\tOK.\n"));
|
|
} // else { AGPLOG(AGP_IRPTRACE, ("\tNO!\n")); }
|
|
break;
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
if (irpStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) {
|
|
Extension->RemovePending = TRUE;
|
|
} else {
|
|
Extension->StopPending = TRUE;
|
|
}
|
|
//
|
|
// If we have given out any interfaces or there are some reserved
|
|
// pages, we cannot stop.
|
|
//
|
|
if ((Extension->InterfaceCount > 0) ||
|
|
(Extension->ReservedPages > 0)) {
|
|
AGPLOG(AGP_NOISE,
|
|
("AgpMasterDispatchPnp: failing %s due to outstanding interfaces\n",
|
|
(irpStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE)
|
|
? "IRP_MN_QUERY_REMOVE_DEVICE"
|
|
: "IRP_MN_QUERY_STOP_DEVICE"
|
|
));
|
|
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return(STATUS_UNSUCCESSFUL);
|
|
} else {
|
|
//
|
|
// We can succeed this, mark our extension as being in limbo so we do
|
|
// not give out any interfaces or anything until we get removed or
|
|
// get a cancel.
|
|
//
|
|
InterlockedIncrement(&Extension->DisableCount);
|
|
break; // forward irp down the stack
|
|
}
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
//
|
|
// This IRP must be handled on the way back up the stack.
|
|
// Set a completion routine to reenable the device.
|
|
//
|
|
if (Extension->RemovePending) {
|
|
Extension->RemovePending = FALSE;
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
AgpCancelMasterRemove,
|
|
Extension,
|
|
TRUE,
|
|
FALSE,
|
|
FALSE);
|
|
return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
|
|
} else {
|
|
//
|
|
// This is a cancel-remove for a query-remove IRP we never saw.
|
|
// Ignore it.
|
|
//
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
//
|
|
// This IRP must be handled on the way back up the stack.
|
|
// Set a completion routine to reenable the device.
|
|
//
|
|
if (Extension->StopPending) {
|
|
Extension->StopPending = FALSE;
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
AgpCancelMasterRemove,
|
|
Extension,
|
|
TRUE,
|
|
FALSE,
|
|
FALSE);
|
|
return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
|
|
} else {
|
|
//
|
|
// This is a cancel-stop for a query-stop IRP we never saw.
|
|
// Ignore it.
|
|
//
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
AGPLOG(AGP_NOISE,
|
|
("AgpMasterDispatchPnp: removing device due to IRP_MN_REMOVE_DEVICE\n"));
|
|
|
|
//
|
|
// PNP is supposed to send us a QUERY_REMOVE before any REMOVE. That is
|
|
// when we check that we are actually in a state where we can be removed.
|
|
// Like all PNP rules, there is an exception - if the START is failed
|
|
// after we have succeeded it, then we get a REMOVE without a QUERY_REMOVE.
|
|
// Obviously this is totally fatal if we have given out interfaces or
|
|
// have pages mapped in the GART. Not much we can do about it then.
|
|
//
|
|
ASSERT(Extension->InterfaceCount == 0);
|
|
ASSERT(Extension->ReservedPages == 0);
|
|
|
|
//
|
|
// Pass the IRP down.
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
Status = IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
|
|
|
|
//
|
|
// Clean up and delete ourselves
|
|
//
|
|
Extension->Target->ChildDevice = NULL;
|
|
Extension->CommonExtension.Deleted = TRUE;
|
|
IoDetachDevice(Extension->CommonExtension.AttachedDevice);
|
|
Extension->CommonExtension.AttachedDevice = NULL;
|
|
RELEASE_BUS_INTERFACE(Extension);
|
|
IoDeleteDevice(DeviceObject);
|
|
return(Status);
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
AGPLOG(AGP_NOISE,
|
|
("AgpMasterDispatchPnp: stopping device due to IRP_MN_STOP_DEVICE\n"));
|
|
ASSERT(Extension->DisableCount);
|
|
|
|
//
|
|
// Just pass the IRP on down
|
|
//
|
|
break;
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
AGPLOG(AGP_NOISE,
|
|
("AgpMasterDispatchPnp: starting device due to IRP_MN_START_DEVICE\n"));
|
|
ASSERT(Extension->DisableCount);
|
|
InterlockedDecrement(&Extension->DisableCount);
|
|
break; // forward IRP down the stack
|
|
}
|
|
|
|
//
|
|
// Just forward to target device
|
|
//
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
|
|
}
|
|
|
|
NTSTATUS
|
|
AgpMasterDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
AGPLOG(AGP_IRPTRACE,
|
|
("AgpMasterDispatchPower: IRP 0x%x\n", irpStack->MinorFunction));
|
|
|
|
//
|
|
// All we keep track of are Dx states. Videoport is responsible for mapping
|
|
// S-states into D states.
|
|
//
|
|
if ((irpStack->MinorFunction == IRP_MN_SET_POWER) &&
|
|
(irpStack->Parameters.Power.Type == DevicePowerState) &&
|
|
(irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
|
|
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// We need to reinitialize the master when this IRP has been completed
|
|
// by the lower drivers. Set up a completion routine.
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
AgpMasterPowerUpCompletion,
|
|
Extension,
|
|
TRUE,
|
|
FALSE,
|
|
FALSE);
|
|
|
|
IoMarkIrpPending(Irp);
|
|
PoStartNextPowerIrp(Irp);
|
|
Status = PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp);
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
//
|
|
// Just forward to target device
|
|
//
|
|
PoStartNextPowerIrp(Irp);
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return(PoCallDriver(Extension->CommonExtension.AttachedDevice, Irp));
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpMasterPowerUpCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Powerup completion routine for the master device. It reinitializes the
|
|
master registers.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - supplies the master device object.
|
|
|
|
Irp - Supplies the IRP_MN_SET_POWER irp.
|
|
|
|
Extension - Supplies the master extension
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG CurrentCapabilities;
|
|
|
|
if (Irp->PendingReturned) {
|
|
IoMarkIrpPending(Irp);
|
|
}
|
|
|
|
Status = AgpInitializeMaster(GET_AGP_CONTEXT_FROM_MASTER(Extension),
|
|
&CurrentCapabilities);
|
|
ASSERT(CurrentCapabilities == Extension->Capabilities);
|
|
if (!NT_SUCCESS(Status)) {
|
|
Irp->IoStatus.Status = Status;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpTargetPowerUpCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PTARGET_EXTENSION Extension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Powerup completion routine for the target device. It reinitializes the
|
|
GART aperture
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - supplies the master device object.
|
|
|
|
Irp - Supplies the IRP_MN_SET_POWER irp.
|
|
|
|
Extension - Supplies the target extension
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
if (Irp->PendingReturned) {
|
|
IoMarkIrpPending(Irp);
|
|
}
|
|
|
|
//
|
|
// Now it is safe to reinitialize the target. All we do here
|
|
// is reset the aperture
|
|
//
|
|
if (Extension->GartLengthInPages != 0) {
|
|
Status = AgpSetAperture(GET_AGP_CONTEXT(Extension),
|
|
Extension->GartBase,
|
|
Extension->GartLengthInPages);
|
|
if (!NT_SUCCESS(Status)) {
|
|
Irp->IoStatus.Status = Status;
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpCancelMasterRemove(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PMASTER_EXTENSION Extension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Completion routine for IRP_MN_CANCEL_REMOVE_DEVICE. This is required
|
|
since we cannot reenable AGP until the lower levels have completed their
|
|
CANCEL_REMOVE processing.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the device object
|
|
|
|
Irp - Supplies the IRP
|
|
|
|
Extension - Supplies the master extension
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
if (Irp->PendingReturned) {
|
|
IoMarkIrpPending(Irp);
|
|
}
|
|
|
|
ASSERT(Extension->DisableCount > 0);
|
|
InterlockedDecrement(&Extension->DisableCount);
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AgpSetEventCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PKEVENT Event
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used as a completion routine when an IRP is passed
|
|
down the stack but more processing must be done on the way back up.
|
|
The effect of using this as a completion routine is that the IRP
|
|
will not be destroyed in IoCompleteRequest as called by the lower
|
|
level object. The event which is a KEVENT is signaled to allow
|
|
processing to continue
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Supplies the device object
|
|
|
|
Irp - The IRP we are processing
|
|
|
|
Event - Supplies the event to be signaled
|
|
|
|
Return Value:
|
|
|
|
STATUS_MORE_PROCESSING_REQUIRED
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(Event);
|
|
|
|
//
|
|
// This can be called at DISPATCH_LEVEL so must not be paged
|
|
//
|
|
KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
|
|
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|