|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
resource.c
Abstract:
Common routines for handling resource requirements
Author:
John Vert (jvert) 10/25/1997
Revision History:
--*/ #include "agplib.h"
PCM_RESOURCE_LIST ApSplitResourceList( IN PCM_RESOURCE_LIST ResourceList, OUT PCM_RESOURCE_LIST *NewResourceList );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, AgpFilterResourceRequirements)
#pragma alloc_text(PAGE, AgpFilterResourceRequirementsHost)
#pragma alloc_text(PAGE, Agp3FilterResourceRequirementsBridge)
#pragma alloc_text(PAGE, AgpStartTarget)
#pragma alloc_text(PAGE, AgpStartTargetHost)
#pragma alloc_text(PAGE, Agp3StartTargetBridge)
#pragma alloc_text(PAGE, ApSplitResourceList)
#endif
static BOOLEAN ResourceConflict = FALSE;
NTSTATUS AgpFilterResourceRequirements( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PTARGET_EXTENSION Extension ) /*++
Routine Dexscription:
One level of indirection through fuinction pointer for non-performance critical filtering of AGP resources during init
Arguments:
DeviceObject - Supplies the device object
Irp - Supplies the IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp
Extension - Supplies the device extension
Return Value:
NTASTATUS
--*/ { PAGED_CODE();
return (Extension->FilterResourceRquirements)(DeviceObject, Irp, Extension); }
NTSTATUS Agp3FilterResourceRequirementsBridge( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PTARGET_EXTENSION Extension ) /*++
Routine Description:
Completion routine for IRP_MN_QUERY_RESOURCE_REQUIREMENTS, we filter in the alternate AGP bridge resource requirements
Arguments:
DeviceObject - Supplies the device object
Irp - Supplies the IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp
Extension - Supplies the device extension
Return Value:
NTSTATUS
--*/ { ULONG ApertureSize; NTSTATUS Status; ULONG AddCount; PHYSICAL_ADDRESS CurrentBase; ULONG CurrentSizeInPages; PIO_RESOURCE_REQUIREMENTS_LIST OldRequirements; PIO_RESOURCE_REQUIREMENTS_LIST NewRequirements; ULONG NewSize; ULONG Alternative; PIO_RESOURCE_LIST OldResourceList; PIO_RESOURCE_LIST NewResourceList; PIO_RESOURCE_DESCRIPTOR Descriptor; PIO_STACK_LOCATION IrpSp; PIO_RESOURCE_LIST ApertureRequirements = NULL; BOOLEAN ResourceFound; BOOLEAN NukeAlternative; ULONG Index; ULONG NewIndex;
PAGED_CODE();
AGPLOG(AGP_NOISE, ("Agp3QueryResourceRequirementsBridge: IRP %08lx, resource %08lx\n", Irp, Irp->IoStatus.Information));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
//
// Create a new resource requirements list with our alternate aperture
// settings tacked onto the bridge's BAR
//
OldRequirements = IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList; if (OldRequirements == NULL) { //STATUS_INVALID_DEVICE_REQUEST
// PNP helpfully passes us a NULL pointer instead of an empty
// resource list when the bridge is disabled. In this case we will
// ignore this irp and not add on our requirements since they are
// not going to be used anyway.
//
return(STATUS_SUCCESS); }
//
// Get the current GART aperture.
//
Status = AgpQueryAperture(GET_AGP_CONTEXT(Extension), &CurrentBase, &CurrentSizeInPages, &ApertureRequirements); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("Agp3QueryResourceRequirementsBridge: AgpQueryAperture %08lx " "failed %08lx\n", Extension, Status)); return(Status); }
AGPLOG(AGP_NOISE, ("Agp3QueryResourceRequirementsBridge: aperture at %I64x, length " "%08lx pages, Requirements %08lx\n", CurrentBase.QuadPart, CurrentSizeInPages, ApertureRequirements));
//
// We will add IO_RESOURCE_DESCRIPTORs to each alternative, after the
// current bridge's BAR
//
//
// Find the AGP bridge BAR's position in the list(s)
//
NukeAlternative = FALSE; ResourceFound = FALSE; OldResourceList = &OldRequirements->List[0];
for (Alternative = 0; Alternative < OldRequirements->AlternativeLists; Alternative++) {
for (Index = 0; Index < OldResourceList->Count; Index++) { Descriptor = &OldResourceList->Descriptors[Index];
if ((Descriptor->Option == IO_RESOURCE_PREFERRED) && (Descriptor->Type == CmResourceTypeMemory)) { if (Descriptor->u.Memory.MinimumAddress.QuadPart == CurrentBase.QuadPart) {
Extension->Agp3BridgeResourceIndex = Index; ResourceFound = TRUE;
//
// Check if PCI already crufted up an alternative
// descriptor that we should nuke
//
if ((Index + 1) < OldResourceList->Count) { Descriptor++; if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE) { NukeAlternative = TRUE; } } break; } } } OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors + OldResourceList->Count); }
//
// No resource in the list matches our current setting!
//
if (!ResourceFound) { AGPLOG(AGP_CRITICAL, ("AGP3 bridge misconfigured, please contact " "system manufacturer for a BIOS upgrade.\n")); AGP_ASSERT(FALSE); return STATUS_INVALID_PARAMETER; // This should be interesting!
}
//
// Again, this should never happen, but if it ever did, then we'd have
// to exit now...
//
if (ApertureRequirements == NULL) { return STATUS_SUCCESS; }
NewSize = (NukeAlternative) ? OldRequirements->ListSize - (OldRequirements->AlternativeLists * sizeof(IO_RESOURCE_DESCRIPTOR)): OldRequirements->ListSize; NewSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (ApertureRequirements->Count * OldRequirements->AlternativeLists); NewRequirements = ExAllocatePool(PagedPool, NewSize); if (NewRequirements == NULL) { ExFreePool(ApertureRequirements); return(STATUS_INSUFFICIENT_RESOURCES); } NewRequirements->ListSize = NewSize; NewRequirements->InterfaceType = OldRequirements->InterfaceType; NewRequirements->BusNumber = OldRequirements->BusNumber; NewRequirements->SlotNumber = OldRequirements->SlotNumber; NewRequirements->AlternativeLists = OldRequirements->AlternativeLists;
//
// Append our requirement to each alternative resource list.
//
NewResourceList = &NewRequirements->List[0]; OldResourceList = &OldRequirements->List[0]; for (Alternative = 0; Alternative < OldRequirements->AlternativeLists; Alternative++) {
//
// Copy the old resource list into the new one.
//
NewResourceList->Version = OldResourceList->Version; NewResourceList->Revision = OldResourceList->Revision; NewResourceList->Count = OldResourceList->Count + ApertureRequirements->Count;
if (NukeAlternative) { NewResourceList->Count--; }
Index = 0; NewIndex = 0; while (Index < OldResourceList->Count) { NewResourceList->Descriptors[NewIndex] = OldResourceList->Descriptors[Index];
//
// This is the AGP bridge BAR, tack on alternatives here
//
if (Index == Extension->Agp3BridgeResourceIndex) { AGP_ASSERT((NewIndex + ApertureRequirements->Count) < NewResourceList->Count); RtlCopyMemory(&NewResourceList->Descriptors[NewIndex + 1], &ApertureRequirements->Descriptors[0], ApertureRequirements->Count * sizeof(IO_RESOURCE_DESCRIPTOR)); NewIndex += ApertureRequirements->Count; if (NukeAlternative) { Index++; } } Index++; NewIndex++; }
//
// Advance to next resource list
//
NewResourceList = (PIO_RESOURCE_LIST)(NewResourceList->Descriptors + NewResourceList->Count); OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors + OldResourceList->Count); }
AGPLOG(AGP_NOISE, ("Agp3QueryResourceRequirementsBridge: IRP %p, old resources %p, " "new resources %p\n", Irp, OldRequirements, NewRequirements));
IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList = NewRequirements; Irp->IoStatus.Information = (ULONG_PTR)NewRequirements; ExFreePool(OldRequirements); ExFreePool(ApertureRequirements);
return STATUS_SUCCESS; }
NTSTATUS AgpFilterResourceRequirementsHost( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PTARGET_EXTENSION Extension ) /*++
Routine Description:
Completion routine for IRP_MN_QUERY_RESOURCE_REQUIREMENTS. This adds on the AGP resource requirements.
Arguments:
DeviceObject - Supplies the device object
Irp - Supplies the IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp
Extension - Supplies the device extension
Return Value:
NTSTATUS
--*/
{ BOOLEAN SwapDescriptor; ULONG SwapLength; ULONG ApertureSize; NTSTATUS Status; ULONG AddCount; PHYSICAL_ADDRESS CurrentBase; PHYSICAL_ADDRESS MaxAddr; ULONG CurrentSizeInPages; PIO_RESOURCE_REQUIREMENTS_LIST OldRequirements; PIO_RESOURCE_REQUIREMENTS_LIST NewRequirements; ULONG NewSize; ULONG Alternative; PIO_RESOURCE_LIST OldResourceList; PIO_RESOURCE_LIST NewResourceList; PIO_RESOURCE_DESCRIPTOR Descriptor; PIO_STACK_LOCATION IrpSp; PIO_RESOURCE_LIST ApertureRequirements = NULL; ULONG i;
PAGED_CODE();
AGPLOG(AGP_NOISE, ("AgpQueryResourceRequirements - IRP %08lx, resource %08lx\n", Irp, Irp->IoStatus.Information));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
//
// Create a new resource requirements list with our current aperture
// settings tacked on the end.
//
OldRequirements = IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList; if (OldRequirements == NULL) { //STATUS_INVALID_DEVICE_REQUEST
// PNP helpfully passes us a NULL pointer instead of an empty resource list
// when the bridge is disabled. In this case we will ignore this irp and not
// add on our requirements since they are not going to be used anyway.
//
return(STATUS_SUCCESS); }
//
// Get the current GART aperture.
//
Status = AgpQueryAperture(GET_AGP_CONTEXT(Extension), &CurrentBase, &CurrentSizeInPages, &ApertureRequirements); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AgpQueryResourceRequirements - AgpQueryAperture %08lx failed %08lx\n", Extension, Status)); return(Status); }
ApertureSize = (CurrentSizeInPages * PAGE_SIZE); MaxAddr.QuadPart = CurrentBase.QuadPart + ApertureSize - 1;
AGPLOG(AGP_NOISE, ("AgpQueryResourceRequirements - aperture at %I64x, length %08lx pages, Requirements %08lx\n", CurrentBase.QuadPart, CurrentSizeInPages, ApertureRequirements));
//
// We will add IO_RESOURCE_DESCRIPTORs to each alternative.
//
// The first one is a private data type marked with our signature. This is
// a marker so that we know which descriptors are ours so we can remove
// them later.
//
// The second is the actual descriptor for the current aperture settings.
// This is marked as preferred.
//
// Following this is the requirements returned from AgpQueryAperture. These
// get marked as alternatives.
//
AddCount = 2;
//
// Enumerate the old list looking for any preferred descriptor that
// conflicts with our preferred settings; if we find one, then the BIOS
// is whack, and we will throw out our preferred descriptor, and let PnP
// choose from our alternates
//
ResourceConflict = FALSE; OldResourceList = &OldRequirements->List[0];
for (Alternative = 0; Alternative < OldRequirements->AlternativeLists; Alternative++) {
for (i = 0; i < OldResourceList->Count; i++) { Descriptor = &OldResourceList->Descriptors[i];
if ((Descriptor->Option == IO_RESOURCE_PREFERRED) && (Descriptor->Type == CmResourceTypeMemory)) { if (((Descriptor->u.Memory.MinimumAddress.QuadPart >= CurrentBase.QuadPart) && (Descriptor->u.Memory.MinimumAddress.QuadPart <= MaxAddr.QuadPart)) || ((Descriptor->u.Memory.MaximumAddress.QuadPart >= CurrentBase.QuadPart) && (Descriptor->u.Memory.MaximumAddress.QuadPart <= MaxAddr.QuadPart)) || ((Descriptor->u.Memory.MinimumAddress.QuadPart < CurrentBase.QuadPart) && (Descriptor->u.Memory.MaximumAddress.QuadPart > MaxAddr.QuadPart))) {
AGPLOG(AGP_CRITICAL, ("AgpQueryResourceRequirements - Conflicted " "resource detected: %I64X - %I64X\n", Descriptor->u.Memory.MinimumAddress.QuadPart, Descriptor->u.Memory.MaximumAddress.QuadPart));
//
// This preferred descriptor is in conflic with our AGP
// preferred setting
//
#if defined(_IA64_)
AGPLOG(AGP_CRITICAL, ("Please contact system manufacturer " "for a BIOS upgrade.\n")); #else // _IA64_
AddCount = 1; ResourceConflict = TRUE; #endif // _IA64_
break; } } } OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors + OldResourceList->Count); }
//
//
// For IA64, PnP cannot reassign the aperture base, so we can only use
// the "preferred" descriptor
//
if (ApertureRequirements) { AddCount += ApertureRequirements->Count; }
NewSize = OldRequirements->ListSize; NewSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (AddCount * OldRequirements->AlternativeLists); NewRequirements = ExAllocatePool(PagedPool, NewSize); if (NewRequirements == NULL) { if (ApertureRequirements) { ExFreePool(ApertureRequirements); } return(STATUS_INSUFFICIENT_RESOURCES); } NewRequirements->ListSize = NewSize; NewRequirements->InterfaceType = OldRequirements->InterfaceType; NewRequirements->BusNumber = OldRequirements->BusNumber; NewRequirements->SlotNumber = OldRequirements->SlotNumber; NewRequirements->AlternativeLists = OldRequirements->AlternativeLists;
//
// Append our requirement to each alternative resource list.
//
NewResourceList = &NewRequirements->List[0]; OldResourceList = &OldRequirements->List[0]; for (Alternative = 0; Alternative < OldRequirements->AlternativeLists; Alternative++) {
//
// Copy the old resource list into the new one.
//
NewResourceList->Version = OldResourceList->Version; NewResourceList->Revision = OldResourceList->Revision; NewResourceList->Count = OldResourceList->Count + AddCount; RtlCopyMemory(&NewResourceList->Descriptors[0], &OldResourceList->Descriptors[0], OldResourceList->Count * sizeof(IO_RESOURCE_DESCRIPTOR));
Descriptor = &NewResourceList->Descriptors[OldResourceList->Count];
//
// Append the marker descriptor
//
Descriptor->Option = 0; Descriptor->Flags = 0; Descriptor->Type = CmResourceTypeDevicePrivate; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; Descriptor->u.DevicePrivate.Data[0] = AgpPrivateResource; Descriptor->u.DevicePrivate.Data[1] = 1; ++Descriptor;
//
// Append the new descriptor
//
if (!ResourceConflict) { Descriptor->Option = IO_RESOURCE_PREFERRED; Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE; Descriptor->Type = CmResourceTypeMemory; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; Descriptor->u.Memory.Length = CurrentSizeInPages * PAGE_SIZE; Descriptor->u.Memory.Alignment = CurrentSizeInPages * PAGE_SIZE; Descriptor->u.Memory.MinimumAddress = CurrentBase; Descriptor->u.Memory.MaximumAddress = MaxAddr; ++Descriptor; }
//
// Append the alternatives
//
if (ApertureRequirements) {
SwapDescriptor = FALSE; for (i = 0; i < ApertureRequirements->Count; i++) { //
// Make sure this descriptor makes sense
//
ASSERT(ApertureRequirements->Descriptors[i].Flags == (CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE)); ASSERT(ApertureRequirements->Descriptors[i].Type == CmResourceTypeMemory); ASSERT(ApertureRequirements->Descriptors[i].ShareDisposition == CmResourceShareDeviceExclusive); *Descriptor = ApertureRequirements->Descriptors[i]; //
// In this case we nuked our preferred descriptor so mark the
// first alternate as preferred
//
if ((i == 0) && ResourceConflict) { Descriptor->Option = IO_RESOURCE_PREFERRED; if (Descriptor->u.Memory.Length != ApertureSize) { SwapLength = Descriptor->u.Memory.Length; Descriptor->u.Memory.Length = ApertureSize; Descriptor->u.Memory.Alignment = ApertureSize; SwapDescriptor = TRUE; } } else { Descriptor->Option = IO_RESOURCE_ALTERNATIVE; if (SwapDescriptor) { if (Descriptor->u.Memory.Length == ApertureSize) { Descriptor->u.Memory.Length = SwapLength; Descriptor->u.Memory.Alignment = SwapLength; SwapDescriptor = FALSE; } } } ++Descriptor; } }
//
// Advance to next resource list
//
NewResourceList = (PIO_RESOURCE_LIST)(NewResourceList->Descriptors + NewResourceList->Count); OldResourceList = (PIO_RESOURCE_LIST)(OldResourceList->Descriptors + OldResourceList->Count); }
AGPLOG(AGP_NOISE, ("AgpQueryResourceRequirements - IRP %p, old resources %p, new resources %p\n", Irp, OldRequirements, NewRequirements)); IrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList = NewRequirements; Irp->IoStatus.Information = (ULONG_PTR)NewRequirements; ExFreePool(OldRequirements); if (ApertureRequirements) { ExFreePool(ApertureRequirements); } return(STATUS_SUCCESS);
}
NTSTATUS AgpQueryResources( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PTARGET_EXTENSION Extension ) /*++
Routine Description:
Completion routine for IRP_MN_QUERY_RESOURCES. This adds on the AGP resources
Arguments:
DeviceObject - Supplies the device object
Irp - Supplies the IRP_MN_QUERY_RESOURCES Irp
Extension - Supplies the device extension
Return Value:
NTSTATUS
--*/
{ if (Irp->PendingReturned) { IoMarkIrpPending(Irp); }
AGPLOG(AGP_NOISE, ("AgpQueryResources - IRP %08lx, resource %08lx\n", Irp, Irp->IoStatus.Information)); return(STATUS_SUCCESS); }
NTSTATUS AgpStartTarget( IN PIRP Irp, IN PTARGET_EXTENSION Extension ) /*++
Routine Description:
One level of indirection through fuinction pointer for non-performance critical initialization of AGP3 target bridge
Arguments:
Irp - supplies the IRP_MN_START_DEVICE Irp.
Extension - Supplies the device extension.
Return Value:
NTSTATUS
--*/
{ PAGED_CODE();
return (Extension->StartTarget)(Irp, Extension); }
NTSTATUS AgpStartTargetHost( IN PIRP Irp, IN PTARGET_EXTENSION Extension ) /*++
Routine Description:
Filters out the AGP-specific resource requirements on a IRP_MN_START_DEVICE Irp.
Arguments:
Irp - supplies the IRP_MN_START_DEVICE Irp.
Extension - Supplies the device extension.
Return Value:
NTSTATUS
--*/
{ PIO_STACK_LOCATION irpSp; PCM_RESOURCE_LIST NewResources; PCM_RESOURCE_LIST NewResourcesTranslated; PCM_RESOURCE_LIST AgpAllocatedResources; PCM_RESOURCE_LIST AgpAllocatedResourcesTranslated; NTSTATUS Status; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
PAGED_CODE();
irpSp = IoGetCurrentIrpStackLocation(Irp);
AGPLOG(AGP_NOISE, ("AgpStartTargetHost: IRP %08lx, resource %08lx\n", Irp, Irp->IoStatus.Information));
if (irpSp->Parameters.StartDevice.AllocatedResources != NULL) { KEVENT event;
//
// Find our private descriptors and split them out into
// our own resource list
//
Extension->Resources = ApSplitResourceList(irpSp->Parameters.StartDevice.AllocatedResources, &NewResources); Extension->ResourcesTranslated = ApSplitResourceList(irpSp->Parameters.StartDevice.AllocatedResourcesTranslated, &NewResourcesTranslated);
//
// Split resources will return two NULL lists when we run low
// memory, so we only need to check one of its return values
//
if ((NewResources == NULL) || (NewResourcesTranslated == NULL)) { Status = STATUS_INSUFFICIENT_RESOURCES;
} else { ASSERT(Extension->Resources->Count == 1); ASSERT(Extension->Resources->List[0].PartialResourceList.Count == 1); Descriptor = &Extension->Resources->List[0].PartialResourceList.PartialDescriptors[0]; ASSERT(Descriptor->Type == CmResourceTypeMemory); Extension->GartBase = Descriptor->u.Memory.Start; Extension->GartLengthInPages = Descriptor->u.Memory.Length / PAGE_SIZE; //
// Set the new GART aperture
//
Status = AgpSetAperture(GET_AGP_CONTEXT(Extension), Extension->GartBase, Extension->GartLengthInPages); }
ASSERT(NT_SUCCESS(Status));
Irp->IoStatus.Status = Status ; if (!NT_SUCCESS(Status) ) { AGPLOG(AGP_CRITICAL, ("AgpStartTargetHost: AgpSetAperture to %I64X, %08lx " "failed %08lx\n", Extension->GartBase.QuadPart, Extension->GartLengthInPages * PAGE_SIZE, Status)); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT);
if (NewResources != NULL) { ExFreePool(NewResources); ExFreePool(Extension->Resources); Extension->Resources = NULL; }
if (NewResourcesTranslated != NULL) { ExFreePool(NewResourcesTranslated); ExFreePool(Extension->ResourcesTranslated); Extension->ResourcesTranslated = NULL; }
return(Status); }
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Set up the new parameters for the PCI driver.
//
irpSp->Parameters.StartDevice.AllocatedResources = NewResources; irpSp->Parameters.StartDevice.AllocatedResourcesTranslated = NewResourcesTranslated; IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, AgpSetEventCompletion, &event, TRUE, TRUE, TRUE);
//
// Pass down the driver stack
//
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; }
ExFreePool(irpSp->Parameters.StartDevice.AllocatedResources); ExFreePool(irpSp->Parameters.StartDevice.AllocatedResourcesTranslated);
IoCompleteRequest(Irp, IO_NO_INCREMENT) ; return Status; } //
// The bridge is disabled, we have been passed a NULL pointer
// instead of an empty resource list. There is nothing to do other
// than pass down the irp
//
IoSkipCurrentIrpStackLocation(Irp);
return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp)); }
NTSTATUS Agp3StartTargetBridge( IN PIRP Irp, IN PTARGET_EXTENSION Extension ) /*++
Routine Description:
Filters out the AGP-specific resource requirements on a IRP_MN_START_DEVICE Irp.
Arguments:
Irp - supplies the IRP_MN_START_DEVICE Irp.
Extension - Supplies the device extension.
Return Value:
NTSTATUS
--*/
{ PIO_STACK_LOCATION irpSp; PCM_RESOURCE_LIST NewResources; PCM_RESOURCE_LIST NewResourcesTranslated; PCM_RESOURCE_LIST AgpAllocatedResources; PCM_RESOURCE_LIST AgpAllocatedResourcesTranslated; NTSTATUS Status; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
PAGED_CODE();
irpSp = IoGetCurrentIrpStackLocation(Irp);
AGPLOG(AGP_NOISE, ("Agp3StartTargetBridge: IRP %08lx, resource %08lx\n", Irp, Irp->IoStatus.Information));
if (irpSp->Parameters.StartDevice.AllocatedResources != NULL) { KEVENT event;
ASSERT(irpSp->Parameters.StartDevice.AllocatedResources->Count == 1);
//
// We better have located our aperture resource, or we're
// in trouble
//
if (Extension->Agp3BridgeResourceIndex == JUNK_INDEX) { Status = STATUS_INVALID_PARAMETER; } else {
ASSERT(irpSp->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList.Count >= Extension->Agp3BridgeResourceIndex); Descriptor = &irpSp->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList.PartialDescriptors[Extension->Agp3BridgeResourceIndex]; ASSERT(Descriptor->Type == CmResourceTypeMemory); Extension->GartBase = Descriptor->u.Memory.Start; Extension->GartLengthInPages = Descriptor->u.Memory.Length / PAGE_SIZE; //
// Set the new GART aperture
//
Status = AgpSetAperture(GET_AGP_CONTEXT(Extension), Extension->GartBase, Extension->GartLengthInPages); } ASSERT(NT_SUCCESS(Status));
Irp->IoStatus.Status = Status; if (!NT_SUCCESS(Status) ) { AGPLOG(AGP_CRITICAL, ("Agp3StartTargetbridge: AgpSetAperture to %I64X, %08lx " "failed %08lx\n", Extension->GartBase.QuadPart, Extension->GartLengthInPages * PAGE_SIZE, Status)); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); }
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Set up the new parameters for the PCI driver.
//
IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, AgpSetEventCompletion, &event, TRUE, TRUE, TRUE);
//
// Pass down the driver stack
//
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; }
IoCompleteRequest(Irp, IO_NO_INCREMENT) ; return Status; } //
// The bridge is disabled, we have been passed a NULL pointer
// instead of an empty resource list. There is nothing to do other
// than pass down the irp
//
IoSkipCurrentIrpStackLocation(Irp);
return(IoCallDriver(Extension->CommonExtension.AttachedDevice, Irp)); }
PCM_RESOURCE_LIST ApSplitResourceList( IN PCM_RESOURCE_LIST ResourceList, OUT PCM_RESOURCE_LIST *NewResourceList ) /*++
Routine Description:
Splits out the AGP-specific resources from a resource list.
Arguments:
ResourceList - Supplies the resource list.
NewResourceList - Returns the new resource list with the AGP-specific resources stripped out.
Return Value:
Pointer to the AGP-specific resource list
--*/
{ ULONG Size; ULONG FullCount; ULONG PartialCount; PCM_FULL_RESOURCE_DESCRIPTOR Full, NewFull, AgpFull; PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial, NewPartial, AgpPartial; PCM_RESOURCE_LIST NewList; PCM_RESOURCE_LIST AgpList; ULONG NextAgp=0;
PAGED_CODE();
//
// First walk through the source resource list and figure out how big it
// is. The two resulting resource lists must be smaller than this, so we
// will just allocate them to be that size and not worry about it.
//
Size = sizeof(CM_RESOURCE_LIST) - sizeof(CM_FULL_RESOURCE_DESCRIPTOR); Full = &ResourceList->List[0]; for (FullCount=0; FullCount<ResourceList->Count; FullCount++) { Size += sizeof(CM_FULL_RESOURCE_DESCRIPTOR); PartialCount = Full->PartialResourceList.Count; Size += (PartialCount-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
Full = (PCM_FULL_RESOURCE_DESCRIPTOR)(&Full->PartialResourceList.PartialDescriptors[PartialCount]); }
//
// Allocate two additional lists
//
NewList = ExAllocatePool(PagedPool, Size); if (NewList == NULL) { *NewResourceList = NULL; return(NULL); }
AgpList = ExAllocatePool(PagedPool, Size); if (AgpList == NULL) { ExFreePool(NewList); *NewResourceList = NULL; return(NULL); }
//
// Initialize both new resource lists to have the same number
// of CM_FULL_RESOURCE_DESCRIPTORs. If any turn out to be empty,
// we will adjust the count.
//
NewList->Count = AgpList->Count = ResourceList->Count;
//
// Walk through each CM_FULL_RESOURCE_DESCRIPTOR, copying as we go.
//
Full = &ResourceList->List[0]; NewFull = &NewList->List[0]; AgpFull = &AgpList->List[0]; for (FullCount = 0;FullCount < ResourceList->Count; FullCount++) { NewFull->InterfaceType = AgpFull->InterfaceType = Full->InterfaceType; NewFull->BusNumber = AgpFull->BusNumber = Full->BusNumber;
//
// Initialize the partial resource list header
//
NewFull->PartialResourceList.Version = Full->PartialResourceList.Version; AgpFull->PartialResourceList.Version = Full->PartialResourceList.Version; NewFull->PartialResourceList.Revision = Full->PartialResourceList.Revision; AgpFull->PartialResourceList.Revision = Full->PartialResourceList.Revision; NewFull->PartialResourceList.Count = AgpFull->PartialResourceList.Count = 0;
NewPartial = &NewFull->PartialResourceList.PartialDescriptors[0]; AgpPartial = &AgpFull->PartialResourceList.PartialDescriptors[0]; for (PartialCount = 0; PartialCount < Full->PartialResourceList.Count; PartialCount++) { Partial = &Full->PartialResourceList.PartialDescriptors[PartialCount]; if ((Partial->Type == CmResourceTypeDevicePrivate) && (Partial->u.DevicePrivate.Data[0] == AgpPrivateResource)) { //
// Found one of our private marker descriptors
//
// For now, the only kind we should see indicates we skip one descriptor
//
ASSERT(NextAgp == 0); ASSERT(Partial->u.DevicePrivate.Data[1] == 1); NextAgp = Partial->u.DevicePrivate.Data[1]; ASSERT(PartialCount+NextAgp < Full->PartialResourceList.Count); } else { //
// if NextAgp is set, this descriptor goes in the AGP-specific list.
// Otherwise, it goes in the new list.
//
if (NextAgp > 0) { --NextAgp; *AgpPartial++ = *Partial; ++AgpFull->PartialResourceList.Count; } else { *NewPartial++ = *Partial; ++NewFull->PartialResourceList.Count; } } }
//
// Finished this CM_PARTIAL_RESOURCE_LIST, advance to the next CM_FULL_RESOURCE_DESCRIPTOR
//
if (NewFull->PartialResourceList.Count == 0) { //
// we can just reuse this partial resource descriptor as it is empty
//
--NewList->Count; } else { NewFull = (PCM_FULL_RESOURCE_DESCRIPTOR)NewPartial; } if (AgpFull->PartialResourceList.Count == 0) { //
// we can just reuse this partial resource descriptor as it is empty
//
--AgpList->Count; } else { AgpFull = (PCM_FULL_RESOURCE_DESCRIPTOR)NewPartial; } }
*NewResourceList = NewList;
return(AgpList); }
|