mirror of
https://github.com/reactos/reactos.git
synced 2026-05-24 16:20:07 +08:00
[VIDEOPRT] Expand how resource usage is handled in videoprt (#8272)
Allows our upcoming PCIX driver to work correctly with it, and now the arbiter on Windows with our videoprt actually matches the behavior and improves video driver compatibility
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
|
||||
extern BOOLEAN VpBaseVideo;
|
||||
|
||||
static UNICODE_STRING VideoClassName = RTL_CONSTANT_STRING(L"VIDEO");
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static BOOLEAN
|
||||
@@ -209,21 +211,41 @@ IntVideoPortReleaseResources(
|
||||
// An empty CM_RESOURCE_LIST
|
||||
UCHAR EmptyResourceList[FIELD_OFFSET(CM_RESOURCE_LIST, List)] = {0};
|
||||
|
||||
Status = IoReportResourceForDetection(
|
||||
DeviceExtension->DriverObject,
|
||||
NULL, 0, /* Driver List */
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
(PCM_RESOURCE_LIST)EmptyResourceList,
|
||||
sizeof(EmptyResourceList),
|
||||
&ConflictDetected);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
if (DeviceExtension->IsLegacyDevice || DeviceExtension->IsLegacyDetect || DeviceExtension->IsVgaDetect)
|
||||
{
|
||||
ERR_(VIDEOPRT,
|
||||
"VideoPortReleaseResources IoReportResource failed with 0x%08lx ; ConflictDetected: %s\n",
|
||||
Status, ConflictDetected ? "TRUE" : "FALSE");
|
||||
Status = IoReportResourceForDetection(
|
||||
DeviceExtension->DriverObject,
|
||||
NULL, 0, /* Driver List */
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
(PCM_RESOURCE_LIST)EmptyResourceList,
|
||||
sizeof(EmptyResourceList),
|
||||
&ConflictDetected);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR_(VIDEOPRT,
|
||||
"VideoPortReleaseResources (Detect) failed with 0x%08lx ; ConflictDetected: %s\n",
|
||||
Status, ConflictDetected ? "TRUE" : "FALSE");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = IoReportResourceUsage(&VideoClassName,
|
||||
DeviceExtension->DriverObject,
|
||||
NULL,
|
||||
0,
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
(PCM_RESOURCE_LIST)EmptyResourceList,
|
||||
sizeof(EmptyResourceList),
|
||||
FALSE,
|
||||
&ConflictDetected);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR_(VIDEOPRT,
|
||||
"VideoPortReleaseResources (Usage) failed with 0x%08lx ; ConflictDetected: %s\n",
|
||||
Status, ConflictDetected ? "TRUE" : "FALSE");
|
||||
}
|
||||
}
|
||||
/* Ignore the returned status however... */
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
@@ -276,6 +298,38 @@ IntVideoPortMapPhysicalMemory(
|
||||
return Status;
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
IntAccessRangeIsInAllocatedResources(
|
||||
_In_ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
_In_ PVIDEO_ACCESS_RANGE Range)
|
||||
{
|
||||
CM_RESOURCE_LIST *Res = DeviceExtension->AllocatedResources;
|
||||
CM_FULL_RESOURCE_DESCRIPTOR *Full;
|
||||
CM_PARTIAL_RESOURCE_DESCRIPTOR *Desc;
|
||||
|
||||
if (!Res || Res->Count == 0)
|
||||
return FALSE;
|
||||
Full = &Res->List[0];
|
||||
for (Desc = Full->PartialResourceList.PartialDescriptors;
|
||||
Desc < Full->PartialResourceList.PartialDescriptors + Full->PartialResourceList.Count;
|
||||
++Desc)
|
||||
{
|
||||
if (Range->RangeInIoSpace && Desc->Type == CmResourceTypePort)
|
||||
{
|
||||
if (Desc->u.Port.Start.QuadPart == Range->RangeStart.QuadPart &&
|
||||
Desc->u.Port.Length == Range->RangeLength)
|
||||
return TRUE;
|
||||
}
|
||||
else if (!Range->RangeInIoSpace && Desc->Type == CmResourceTypeMemory)
|
||||
{
|
||||
if (Desc->u.Memory.Start.QuadPart == Range->RangeStart.QuadPart &&
|
||||
Desc->u.Memory.Length == Range->RangeLength)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
PVOID NTAPI
|
||||
IntVideoPortMapMemory(
|
||||
@@ -952,12 +1006,82 @@ VideoPortVerifyAccessRanges(
|
||||
{
|
||||
/* Release the resources and do nothing more for now... */
|
||||
IntVideoPortReleaseResources(DeviceExtension);
|
||||
/* If releasing VGA device resources, clear tracked ranges */
|
||||
if (DeviceExtension->IsVgaDriver)
|
||||
{
|
||||
KeWaitForMutexObject(&VgaSyncLock, Executive, KernelMode, FALSE, NULL);
|
||||
if (VgaRanges)
|
||||
{
|
||||
ExFreePoolWithTag(VgaRanges, TAG_VIDEO_PORT);
|
||||
VgaRanges = NULL;
|
||||
}
|
||||
NumOfVgaRanges = 0;
|
||||
VgaDeviceExtension = NULL;
|
||||
KeReleaseMutex(&VgaSyncLock, FALSE);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/* Create the resource list */
|
||||
/*
|
||||
* For non-legacy PCI devices, validate that the relevant I/O or memory
|
||||
* decoding bits are enabled in the PCI command register before claiming
|
||||
*/
|
||||
if (!DeviceExtension->IsLegacyDevice && DeviceExtension->AdapterInterfaceType == PCIBus)
|
||||
{
|
||||
USHORT PciCommand;
|
||||
ULONG BytesRead;
|
||||
|
||||
BytesRead = HalGetBusDataByOffset(PCIConfiguration,
|
||||
DeviceExtension->SystemIoBusNumber,
|
||||
DeviceExtension->SystemIoSlotNumber,
|
||||
&PciCommand,
|
||||
FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
|
||||
sizeof(PciCommand));
|
||||
if (BytesRead == sizeof(PciCommand))
|
||||
{
|
||||
for (i = 0; i < NumAccessRanges; i++)
|
||||
{
|
||||
if (AccessRanges[i].RangeInIoSpace)
|
||||
{
|
||||
if ((PciCommand & PCI_ENABLE_IO_SPACE) == 0)
|
||||
{
|
||||
WARN_(VIDEOPRT, "PCI I/O space disabled; refusing access range claim\n");
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((PciCommand & PCI_ENABLE_MEMORY_SPACE) == 0)
|
||||
{
|
||||
WARN_(VIDEOPRT, "PCI memory space disabled; refusing access range claim\n");
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine which ranges need to be claimed (exclude PnP-assigned ones) */
|
||||
ULONG Needed = 0;
|
||||
for (i = 0; i < NumAccessRanges; ++i)
|
||||
{
|
||||
if (DeviceExtension->PhysicalDeviceObject && !DeviceExtension->IsLegacyDevice)
|
||||
{
|
||||
if (IntAccessRangeIsInAllocatedResources(DeviceExtension, &AccessRanges[i]))
|
||||
continue;
|
||||
}
|
||||
++Needed;
|
||||
}
|
||||
|
||||
if (Needed == 0)
|
||||
{
|
||||
/* Nothing to report/claim */
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/* Create the resource list for the non-PnP-assigned ranges */
|
||||
ResourceListSize = sizeof(CM_RESOURCE_LIST)
|
||||
+ (NumAccessRanges - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||||
+ (Needed - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||||
ResourceList = ExAllocatePoolWithTag(PagedPool, ResourceListSize, TAG_VIDEO_PORT);
|
||||
if (!ResourceList)
|
||||
{
|
||||
@@ -971,47 +1095,86 @@ VideoPortVerifyAccessRanges(
|
||||
ResourceList->List[0].BusNumber = DeviceExtension->SystemIoBusNumber;
|
||||
ResourceList->List[0].PartialResourceList.Version = 1;
|
||||
ResourceList->List[0].PartialResourceList.Revision = 1;
|
||||
ResourceList->List[0].PartialResourceList.Count = NumAccessRanges;
|
||||
for (i = 0; i < NumAccessRanges; i++, AccessRanges++)
|
||||
ResourceList->List[0].PartialResourceList.Count = Needed;
|
||||
|
||||
ULONG j = 0;
|
||||
for (i = 0; i < NumAccessRanges; ++i)
|
||||
{
|
||||
PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
|
||||
if (AccessRanges->RangeInIoSpace)
|
||||
if (DeviceExtension->PhysicalDeviceObject && !DeviceExtension->IsLegacyDevice)
|
||||
{
|
||||
if (IntAccessRangeIsInAllocatedResources(DeviceExtension, &AccessRanges[i]))
|
||||
continue;
|
||||
}
|
||||
|
||||
PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[j++];
|
||||
if (AccessRanges[i].RangeInIoSpace)
|
||||
{
|
||||
PartialDescriptor->Type = CmResourceTypePort;
|
||||
PartialDescriptor->u.Port.Start = AccessRanges->RangeStart;
|
||||
PartialDescriptor->u.Port.Length = AccessRanges->RangeLength;
|
||||
PartialDescriptor->u.Port.Start = AccessRanges[i].RangeStart;
|
||||
PartialDescriptor->u.Port.Length = AccessRanges[i].RangeLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
PartialDescriptor->Type = CmResourceTypeMemory;
|
||||
PartialDescriptor->u.Memory.Start = AccessRanges->RangeStart;
|
||||
PartialDescriptor->u.Memory.Length = AccessRanges->RangeLength;
|
||||
PartialDescriptor->u.Memory.Start = AccessRanges[i].RangeStart;
|
||||
PartialDescriptor->u.Memory.Length = AccessRanges[i].RangeLength;
|
||||
}
|
||||
if (AccessRanges->RangeShareable)
|
||||
PartialDescriptor->ShareDisposition = CmResourceShareShared;
|
||||
else
|
||||
PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||||
PartialDescriptor->ShareDisposition = AccessRanges[i].RangeShareable ?
|
||||
CmResourceShareShared : CmResourceShareDeviceExclusive;
|
||||
PartialDescriptor->Flags = 0;
|
||||
if (AccessRanges->RangePassive & VIDEO_RANGE_PASSIVE_DECODE)
|
||||
if (AccessRanges[i].RangePassive & VIDEO_RANGE_PASSIVE_DECODE)
|
||||
PartialDescriptor->Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
|
||||
if (AccessRanges->RangePassive & VIDEO_RANGE_10_BIT_DECODE)
|
||||
if (AccessRanges[i].RangePassive & VIDEO_RANGE_10_BIT_DECODE)
|
||||
PartialDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
|
||||
}
|
||||
|
||||
/* Try to acquire all resource ranges */
|
||||
Status = IoReportResourceForDetection(
|
||||
DeviceExtension->DriverObject,
|
||||
NULL, 0, /* Driver List */
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
ResourceList, ResourceListSize,
|
||||
&ConflictDetected);
|
||||
if (DeviceExtension->IsLegacyDevice || DeviceExtension->IsLegacyDetect || DeviceExtension->IsVgaDetect)
|
||||
{
|
||||
Status = IoReportResourceForDetection(
|
||||
DeviceExtension->DriverObject,
|
||||
NULL, 0, /* Driver List */
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
ResourceList, ResourceListSize,
|
||||
&ConflictDetected);
|
||||
|
||||
/* IntIsVgaSaveDriver() will later ignore STATUS_CONFLICTING_ADDRESSES, but we still claim it */
|
||||
if (!NT_SUCCESS(Status) && IntIsVgaSaveDriver(DeviceExtension))
|
||||
{
|
||||
NTSTATUS fbStatus;
|
||||
BOOLEAN fbConflict = FALSE;
|
||||
fbStatus = IoReportResourceUsage(&VideoClassName,
|
||||
DeviceExtension->DriverObject,
|
||||
NULL,
|
||||
0,
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
ResourceList,
|
||||
ResourceListSize,
|
||||
FALSE,
|
||||
&fbConflict);
|
||||
INFO_(VIDEOPRT, "VGA detect->usage fallback: Status=0x%lx Conflict=%d fbStatus=0x%lx fbConflict=%d\n",
|
||||
Status, ConflictDetected, fbStatus, fbConflict);
|
||||
Status = fbStatus;
|
||||
ConflictDetected = fbConflict;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = IoReportResourceUsage(&VideoClassName,
|
||||
DeviceExtension->DriverObject,
|
||||
NULL,
|
||||
0,
|
||||
DeviceExtension->PhysicalDeviceObject,
|
||||
ResourceList,
|
||||
ResourceListSize,
|
||||
FALSE,
|
||||
&ConflictDetected);
|
||||
}
|
||||
ExFreePoolWithTag(ResourceList, TAG_VIDEO_PORT);
|
||||
|
||||
/* If VgaSave driver is conflicting and we don't explicitely want
|
||||
* to use it, ignore the problem (because win32k will try to use
|
||||
* this driver only if all other ones are failing). */
|
||||
if (Status == STATUS_CONFLICTING_ADDRESSES &&
|
||||
if ((Status == STATUS_CONFLICTING_ADDRESSES || ConflictDetected) &&
|
||||
IntIsVgaSaveDriver(DeviceExtension) &&
|
||||
!VpBaseVideo)
|
||||
{
|
||||
@@ -1021,7 +1184,34 @@ VideoPortVerifyAccessRanges(
|
||||
if (!NT_SUCCESS(Status) || ConflictDetected)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
else
|
||||
{
|
||||
/* Track VGA access ranges on success for fallback handling */
|
||||
if (DeviceExtension->IsVgaDriver)
|
||||
{
|
||||
KeWaitForMutexObject(&VgaSyncLock, Executive, KernelMode, FALSE, NULL);
|
||||
if (VgaRanges)
|
||||
{
|
||||
ExFreePoolWithTag(VgaRanges, TAG_VIDEO_PORT);
|
||||
VgaRanges = NULL;
|
||||
NumOfVgaRanges = 0;
|
||||
}
|
||||
if (NumAccessRanges)
|
||||
{
|
||||
SIZE_T sz = NumAccessRanges * sizeof(VIDEO_ACCESS_RANGE);
|
||||
VgaRanges = ExAllocatePoolWithTag(PagedPool, sz, TAG_VIDEO_PORT);
|
||||
if (VgaRanges)
|
||||
{
|
||||
RtlCopyMemory(VgaRanges, AccessRanges, sz);
|
||||
NumOfVgaRanges = NumAccessRanges;
|
||||
VgaDeviceExtension = DeviceExtension;
|
||||
}
|
||||
}
|
||||
KeReleaseMutex(&VgaSyncLock, FALSE);
|
||||
}
|
||||
/* Leave VGA detect phase after first successful claim */
|
||||
DeviceExtension->IsVgaDetect = FALSE;
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -42,9 +42,20 @@ BOOLEAN VideoPortUseNewKey = FALSE;
|
||||
|
||||
KSPIN_LOCK HwResetAdaptersLock;
|
||||
RTL_STATIC_LIST_HEAD(HwResetAdaptersList);
|
||||
KMUTEX VgaSyncLock;
|
||||
PVIDEO_PORT_DEVICE_EXTENSION VgaDeviceExtension = NULL;
|
||||
PVIDEO_ACCESS_RANGE VgaRanges = NULL;
|
||||
ULONG NumOfVgaRanges = 0;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static BOOLEAN
|
||||
IntIsVgaSaveDriverName(_In_ PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
static const UNICODE_STRING VgaSave = RTL_CONSTANT_STRING(L"\\Driver\\VgaSave");
|
||||
return RtlEqualUnicodeString(&VgaSave, &DriverObject->DriverName, TRUE);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
@@ -423,8 +434,13 @@ IntVideoPortFindAdapter(
|
||||
SYSTEM_BASIC_INFORMATION SystemBasicInfo;
|
||||
UCHAR Again = FALSE;
|
||||
BOOL LegacyDetection = FALSE;
|
||||
BOOLEAN VgaResourcesReleased = FALSE;
|
||||
|
||||
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
DeviceExtension->IsVgaDriver = IntIsVgaSaveDriverName(DriverObject);
|
||||
DeviceExtension->IsVgaDetect = DeviceExtension->IsVgaDriver;
|
||||
DeviceExtension->IsLegacyDetect = FALSE;
|
||||
DeviceExtension->ReportDevice = FALSE;
|
||||
|
||||
/* Setup a ConfigInfo structure that we will pass to HwFindAdapter. */
|
||||
RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
|
||||
@@ -462,7 +478,25 @@ IntVideoPortFindAdapter(
|
||||
if (DeviceExtension->PhysicalDeviceObject == NULL)
|
||||
{
|
||||
LegacyDetection = TRUE;
|
||||
DeviceExtension->IsLegacyDevice = TRUE;
|
||||
DeviceExtension->IsLegacyDetect = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceExtension->IsLegacyDevice = FALSE;
|
||||
}
|
||||
|
||||
/* If we already have a VGA miniport and are about to probe for additional adapters,
|
||||
* release its resources temporarily so conflicts are visible during detection.
|
||||
* We'll reclaim them later if no new adapter successfully claims them. */
|
||||
KeWaitForMutexObject(&VgaSyncLock, Executive, KernelMode, FALSE, NULL);
|
||||
if (VgaDeviceExtension)
|
||||
{
|
||||
INFO_(VIDEOPRT, "Temporarily releasing VGA resources for adapter probing\n");
|
||||
IntVideoPortReleaseResources(VgaDeviceExtension);
|
||||
VgaResourcesReleased = TRUE;
|
||||
}
|
||||
KeReleaseMutex(&VgaSyncLock, FALSE);
|
||||
|
||||
if (LegacyDetection)
|
||||
{
|
||||
@@ -521,7 +555,28 @@ IntVideoPortFindAdapter(
|
||||
|
||||
if (vpStatus != NO_ERROR)
|
||||
{
|
||||
ERR_(VIDEOPRT, "HwFindAdapter call failed with error 0x%X\n", vpStatus);
|
||||
ERR_(VIDEOPRT, "HwFindAdapter failed (vpStatus=0x%X) bus=%u iface=%u legacy=%u vga=%u detect(VGA=%u LEGACY=%u)\n",
|
||||
vpStatus,
|
||||
DeviceExtension->SystemIoBusNumber,
|
||||
DeviceExtension->AdapterInterfaceType,
|
||||
DeviceExtension->IsLegacyDevice,
|
||||
DeviceExtension->IsVgaDriver,
|
||||
DeviceExtension->IsVgaDetect,
|
||||
DeviceExtension->IsLegacyDetect);
|
||||
/* If we released VGA resources, reclaim them so VGA fallback still works */
|
||||
if (VgaResourcesReleased)
|
||||
{
|
||||
if (VgaDeviceExtension && VgaRanges && NumOfVgaRanges)
|
||||
{
|
||||
INFO_(VIDEOPRT, "Reclaiming VGA resources after failed probe\n");
|
||||
if (VideoPortVerifyAccessRanges(&VgaDeviceExtension->MiniPortDeviceExtension,
|
||||
NumOfVgaRanges,
|
||||
VgaRanges) != NO_ERROR)
|
||||
{
|
||||
WARN_(VIDEOPRT, "Failed to reclaim VGA resources after probe failure\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto Failure;
|
||||
}
|
||||
@@ -559,6 +614,75 @@ IntVideoPortFindAdapter(
|
||||
&HwResetAdaptersLock);
|
||||
}
|
||||
|
||||
if (DeviceExtension->IsVgaDriver)
|
||||
{
|
||||
KeWaitForMutexObject(&VgaSyncLock, Executive, KernelMode, FALSE, NULL);
|
||||
if (VgaDeviceExtension == NULL)
|
||||
{
|
||||
VgaDeviceExtension = DeviceExtension;
|
||||
}
|
||||
KeReleaseMutex(&VgaSyncLock, FALSE);
|
||||
}
|
||||
|
||||
DeviceExtension->IsVgaDetect = FALSE;
|
||||
DeviceExtension->IsLegacyDetect = FALSE;
|
||||
|
||||
/* For legacy (non-PnP) adapters we should report a detected device so that
|
||||
* a PDO exists for higher layers to enumerate consistently (mirrors ScsiPort).*/
|
||||
if (DeviceExtension->IsLegacyDevice && !DeviceExtension->ReportDevice)
|
||||
{
|
||||
PDEVICE_OBJECT ReportedPdo = NULL;
|
||||
NTSTATUS repStatus = IoReportDetectedDevice(DriverObject,
|
||||
DeviceExtension->AdapterInterfaceType,
|
||||
DeviceExtension->SystemIoBusNumber,
|
||||
DeviceExtension->SystemIoSlotNumber,
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
&ReportedPdo);
|
||||
if (!NT_SUCCESS(repStatus))
|
||||
{
|
||||
WARN_(VIDEOPRT, "IoReportDetectedDevice failed 0x%08lx (bus=%u slot=%u)\n",
|
||||
repStatus,
|
||||
DeviceExtension->SystemIoBusNumber,
|
||||
DeviceExtension->SystemIoSlotNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_(VIDEOPRT, "Reported legacy adapter PDO %p (bus=%u slot=%u)\n",
|
||||
ReportedPdo,
|
||||
DeviceExtension->SystemIoBusNumber,
|
||||
DeviceExtension->SystemIoSlotNumber);
|
||||
DeviceExtension->ReportDevice = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to reclaim VGA resources after probing if a VGA device exists */
|
||||
if (VgaDeviceExtension && VgaRanges && NumOfVgaRanges)
|
||||
{
|
||||
VP_STATUS vr;
|
||||
INFO_(VIDEOPRT, "Attempt VGA reclaim after probe (ranges=%lu)\n", NumOfVgaRanges);
|
||||
vr = VideoPortVerifyAccessRanges(&VgaDeviceExtension->MiniPortDeviceExtension,
|
||||
NumOfVgaRanges,
|
||||
VgaRanges);
|
||||
if (vr != NO_ERROR)
|
||||
{
|
||||
/* Another driver has taken VGA resources; drop fallback state */
|
||||
WARN_(VIDEOPRT, "VGA reclaim failed (vpStatus=0x%X); releasing fallback state\n", vr);
|
||||
KeWaitForMutexObject(&VgaSyncLock, Executive, KernelMode, FALSE, NULL);
|
||||
ExFreePoolWithTag(VgaRanges, TAG_VIDEO_PORT);
|
||||
VgaRanges = NULL;
|
||||
NumOfVgaRanges = 0;
|
||||
VgaDeviceExtension = NULL;
|
||||
KeReleaseMutex(&VgaSyncLock, FALSE);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_(VIDEOPRT, "VGA reclaim succeeded\n");
|
||||
}
|
||||
}
|
||||
|
||||
INFO_(VIDEOPRT, "STATUS_SUCCESS\n");
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
@@ -566,6 +690,21 @@ Failure:
|
||||
RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
|
||||
if (DeviceExtension->NextDeviceObject)
|
||||
IoDetachDevice(DeviceExtension->NextDeviceObject);
|
||||
|
||||
/* Explicitly reclaim VGA resources on complete failure */
|
||||
if (VgaResourcesReleased)
|
||||
{
|
||||
if (VgaDeviceExtension && VgaRanges && NumOfVgaRanges)
|
||||
{
|
||||
INFO_(VIDEOPRT, "Final reclaim attempt of VGA resources during failure cleanup\n");
|
||||
if (VideoPortVerifyAccessRanges(&VgaDeviceExtension->MiniPortDeviceExtension,
|
||||
NumOfVgaRanges,
|
||||
VgaRanges) != NO_ERROR)
|
||||
{
|
||||
WARN_(VIDEOPRT, "VGA reclaim failed during failure cleanup\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
IoDeleteDevice(DeviceObject);
|
||||
return Status;
|
||||
}
|
||||
@@ -802,6 +941,7 @@ VideoPortInitialize(
|
||||
{
|
||||
FirstInitialization = TRUE;
|
||||
KeInitializeMutex(&VideoPortInt10Mutex, 0);
|
||||
KeInitializeMutex(&VgaSyncLock, 0);
|
||||
KeInitializeSpinLock(&HwResetAdaptersLock);
|
||||
IntLoadRegistryParameters();
|
||||
}
|
||||
|
||||
@@ -110,6 +110,11 @@ typedef struct _VIDEO_PORT_DEVICE_EXTENSTION
|
||||
USHORT AdapterNumber;
|
||||
USHORT DisplayNumber;
|
||||
ULONG NumberOfSecondaryDisplays;
|
||||
BOOLEAN IsLegacyDevice;
|
||||
BOOLEAN IsLegacyDetect;
|
||||
BOOLEAN IsVgaDriver;
|
||||
BOOLEAN IsVgaDetect;
|
||||
BOOLEAN ReportDevice;
|
||||
CHAR POINTER_ALIGNMENT MiniPortDeviceExtension[1];
|
||||
} VIDEO_PORT_DEVICE_EXTENSION, *PVIDEO_PORT_DEVICE_EXTENSION;
|
||||
|
||||
@@ -257,6 +262,10 @@ extern BOOLEAN VideoPortUseNewKey;
|
||||
|
||||
extern KSPIN_LOCK HwResetAdaptersLock;
|
||||
extern LIST_ENTRY HwResetAdaptersList;
|
||||
extern KMUTEX VgaSyncLock;
|
||||
extern PVIDEO_PORT_DEVICE_EXTENSION VgaDeviceExtension;
|
||||
extern PVIDEO_ACCESS_RANGE VgaRanges;
|
||||
extern ULONG NumOfVgaRanges;
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
|
||||
Reference in New Issue
Block a user