📄 init.c
字号:
PHYSICAL_ADDRESS MaxMemory;
//
// Maximum memory address for limiting AGP memory to below 4GB
//
MAX_MEM(MaxMemory.QuadPart);
//
// Get an event to wait on
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Get a PDO where we will send the request IRP.
LowerPdo = Extension->CommonExtension.AttachedDevice;
//
// Initialize the input parameters and the output buffer.
//
RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) );
inputBuffer.MethodNameAsUlong = CM_BANK_METHOD;
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)ResultBuffer;
//
// Build the request to call the BANK method.
//
Irp = IoBuildDeviceIoControlRequest(
IOCTL_ACPI_EVAL_METHOD,
LowerPdo,
&inputBuffer,
sizeof(ACPI_EVAL_INPUT_BUFFER),
outputBuffer,
sizeof(ResultBuffer),
FALSE,
&event,
&IoStatus
);
if (!Irp)
{
return;
}
//
// Send to the ACPI driver
//
Status = IoCallDriver ( LowerPdo, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (NT_SUCCESS(Status))
{
AGPLOG(AGP_NOISE, ("AGPLIB: ACPI BANK Method Executed.\n"));
//
// Sanity check method results
//
MethodArg = outputBuffer->Argument;
if ((outputBuffer->Signature == ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) &&
(MethodArg->DataLength >= sizeof(MBAT)) &&
(MethodArg->Type == ACPI_METHOD_ARGUMENT_BUFFER))
{
AGPLOG(AGP_NOISE, ("AGPLIB: MBAT appears valid.\n"));
//
// Grab the MBAT and see if we can parse it
//
Mbat = (PMBAT)MethodArg->Data;
if (Mbat->TableVersion == MBAT_VERSION) {
AGPLOG(AGP_NOISE, ("AGPLIB: Parsing MBAT.\n"));
//
// Calculate the number of favored ranges mentioned
// in the MBAT
//
i=Mbat->ValidEntryBitmap;
while(i)
{
Extension->FavoredMemory.NumRanges++;
i = i & (i-1);
}
AGPLOG(AGP_NOISE, ("AGPLIB: %u favored ranges found.\n",
Extension->FavoredMemory.NumRanges));
if(Extension->FavoredMemory.NumRanges == 0) return;
//
// Allocate the favored memory range structure in our device
// extension
//
Extension->FavoredMemory.Ranges =
ExAllocatePool(NonPagedPool, sizeof(AGP_MEMORY_RANGE) *
Extension->FavoredMemory.NumRanges);
if (Extension->FavoredMemory.Ranges == NULL) {
Extension->FavoredMemory.NumRanges = 0;
return;
}
//
// Initialize the favored memory ranges in our extension
// based upon the MBAT
//
i=0;
j=0;
while(Mbat->ValidEntryBitmap)
{
if (Mbat->ValidEntryBitmap & 1)
{
if (Mbat->DecodeRange[i].Lower.QuadPart > MaxMemory.QuadPart) {
// This range is invalid since its lower address is above
// the highest allowable address
AGPLOG(AGP_NOISE, ("AGPLIB: Invalid MBAT Range ==> %I64x - %I64x\n",
Mbat->DecodeRange[i].Lower.QuadPart,
Mbat->DecodeRange[i].Upper.QuadPart));
// Pretend like this range never existed ...
//
Extension->FavoredMemory.NumRanges--;
}
else
{
// This is a valid range.
Extension->FavoredMemory.Ranges[j].Lower.QuadPart =
Mbat->DecodeRange[i].Lower.QuadPart;
Extension->FavoredMemory.Ranges[j].Upper.QuadPart =
Mbat->DecodeRange[i].Upper.QuadPart;
AGPLOG(AGP_NOISE, ("AGPLIB: MBAT Range ==> %I64x - %I64x\n",
Mbat->DecodeRange[i].Lower.QuadPart,
Mbat->DecodeRange[i].Upper.QuadPart));
if(Extension->FavoredMemory.Ranges[j].Upper.QuadPart >
MaxMemory.QuadPart)
{
AGPLOG(AGP_NOISE, ("AGPLIB: Adjusting range to fit within maximum allowable address.\n"));
Extension->FavoredMemory.Ranges[j].Upper.QuadPart =
MaxMemory.QuadPart;
}
j++;
}
}
Mbat->ValidEntryBitmap >>= 1;
i++;
}
} else {
AGPLOG(AGP_WARNING, ("AGPLIB: Unknown MBAT version.\n"));
}
}
}
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Entrypoint needed to initialize the AGP filter.
Arguments:
DriverObject - Pointer to the driver object created by the system.
RegistryPath - Pointer to the unicode registry service path.
Return Value:
NT status.
--*/
{
NTSTATUS Status;
HANDLE serviceKey, paramsKey;
UNICODE_STRING UnicodeString;
OBJECT_ATTRIBUTES attributes;
PAGED_CODE();
AgpDriver = DriverObject;
DriverObject->DriverExtension->AddDevice = AgpAddDevice;
DriverObject->DriverUnload = AgpDriverUnload;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AgpDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = AgpDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = AgpDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = AgpDispatchWmi;
RtlInitUnicodeString(&UnicodeString,
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
L"Control");
//
// Open the global hack key and retrieve the gloabl hack table
//
InitializeObjectAttributes(&attributes,
&UnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = ZwOpenKey(&serviceKey,
KEY_READ,
&attributes
);
//
// We must succeed here, there are devices that can freeze a system,
// and something is really wrong if we can't access these values
//
if (!NT_SUCCESS(Status)) {
return Status;
}
AgpOpenKey(L"AGP", serviceKey, ¶msKey, &Status);
ZwClose(serviceKey);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = AgpBuildHackTable(&AgpGlobalHackTable, paramsKey);
ZwClose(paramsKey);
if (!NT_SUCCESS(Status)) {
return Status;
}
//
// Open our service key and retrieve any platform hack(s)
//
InitializeObjectAttributes(&attributes,
RegistryPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = ZwOpenKey(&serviceKey,
KEY_READ,
&attributes
);
//
// Maybe their chipset is so burly, it doesn't require any hacks!
//
if (!NT_SUCCESS(Status)) {
return STATUS_SUCCESS;
}
AgpOpenKey(L"Parameters", serviceKey, ¶msKey, &Status);
ZwClose(serviceKey);
//
// Don't care
//
if (!NT_SUCCESS(Status)) {
return STATUS_SUCCESS;
}
//
// Again, disregard status
//
AgpBuildHackTable(&AgpDeviceHackTable, paramsKey);
ZwClose(paramsKey);
return STATUS_SUCCESS;
}
VOID
AgpDriverUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Entrypoint used to unload the AGP driver
Arguments:
DriverObject - Pointer to the driver object created by the system
Return Value:
None
--*/
{
if (AgpDeviceHackTable != NULL) {
ExFreePool(AgpDeviceHackTable);
AgpDeviceHackTable = NULL;
}
if (AgpGlobalHackTable != NULL) {
ExFreePool(AgpGlobalHackTable);
AgpGlobalHackTable = NULL;
}
}
NTSTATUS
AgpAttachDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PTARGET_EXTENSION Extension
)
/*++
Routine Description:
Completion routine for BusRelations IRP_MN_QUERY_DEVICE_RELATIONS irps sent
to the PCI-PCI bridge PDO. In order to handle QUERY_INTERFACE irps sent
from the AGP device, we must attach to its PDO. That means we attach to
all the child PDOs of the PCI-PCI bridge.
Arguments:
DeviceObject - Supplies the device object
Irp - Supplies the IRP_MN_QUERY_DEVICE_RELATIONS irp
Extension - Supplies the AGP device extension.
Return Value:
NTSTATUS
--*/
{
NTSTATUS Status;
PDEVICE_RELATIONS Relations;
ULONG i;
PDEVICE_OBJECT NewDevice;
PMASTER_EXTENSION NewExtension;
#if DBG
ULONG MasterCount=0;
#endif
PAGED_CODE();
//
// If we have already attached, don't do it again.
//
if (Extension->ChildDevice != NULL) {
return(STATUS_SUCCESS);
}
Relations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
//
// If somebody completed the IRP with success, but never
// filled in the Relations field, then assume there are
// no children and we don't have to do anything.
//
if (Relations == NULL) {
return(STATUS_SUCCESS);
}
for (i=0; i<Relations->Count; i++) {
//
// Create a device object to attach to this PDO.
//
Status = IoCreateDevice(AgpDriver,
sizeof(MASTER_EXTENSION),
NULL,
FILE_DEVICE_BUS_EXTENDER,
0,
FALSE,
&NewDevice);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,("AgpAttachDeviceRelations: IoCreateDevice failed %08lx\n",Status));
continue;
}
//
// Initialize the device extension
//
NewExtension = NewDevice->DeviceExtension;
NewExtension->CommonExtension.Deleted = FALSE;
NewExtension->CommonExtension.Type = AgpMasterFilter;
NewExtension->CommonExtension.Signature = MASTER_SIG;
Status = ApQueryBusInterface(Relations->Objects[i], &NewExtension->CommonExtension.BusInterface);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AgpAttachDeviceRelations: query for bus interface failed %08lx\n", Status));
IoDeleteDevice(NewDevice);
continue;
}
NewExtension->Target = Extension;
NewExtension->InterfaceCount = 0;
NewExtension->ReservedPages = 0;
NewExtension->StopPending = FALSE;
NewExtension->RemovePending = FALSE;
NewExtension->DisableCount = 1; // biased so that we don't give anything out
// until we see the IRP_MN_START
Extension->ChildDevice = NewExtension;
//
// Attach to the specified device
//
NewExtension->CommonExtension.AttachedDevice = IoAttachDeviceToDeviceStack(NewDevice, Relations->Objects[i]);
if (NewExtension->CommonExtension.AttachedDevice == NULL) {
//
// The attach failed. Not really fatal, AGP just won't work for that device.
//
AGPLOG(AGP_CRITICAL,
("AgpAttachDeviceRelations: IoAttachDeviceToDeviceStack from %08lx to %08lx failed\n",
NewDevice,
Relations->Objects[i]));
RELEASE_BUS_INTERFACE(NewExtension);
IoDeleteDevice(NewDevice);
continue;
}
//
// Propagate the PDO's requirements
//
NewDevice->StackSize = NewExtension->CommonExtension.AttachedDevice->StackSize + 1;
NewDevice->AlignmentRequirement = NewExtension->CommonExtension.AttachedDevice->AlignmentRequirement;
if (NewExtension->CommonExtension.AttachedDevice->Flags & DO_POWER_PAGABLE) {
NewDevice->Flags |= DO_POWER_PAGABLE;
}
//
// Finally call the chipset-specific code for master initialization
//
Status = AgpInitializeMaster(GET_AGP_CONTEXT(Extension),
&NewExtension->Capabilities);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AgpAttachDeviceRelations: AgpInitializeMaster on device %08lx failed %08lx\n",
NewDevice,
Status));
IoDetachDevice(NewExtension->CommonExtension.AttachedDevice);
RELEASE_BUS_INTERFACE(NewExtension);
IoDeleteDevice(NewDevice);
continue;
}
NewDevice->Flags &= ~DO_DEVICE_INITIALIZING;
#if DBG
//
// Check to make sure there is only one AGP master on the bus. There can be more
// than one device (multifunction device) but only one must have AGP capabilities
//
MasterCount++;
ASSERT(MasterCount == 1);
#else
break;
#endif
}
return(STATUS_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -