mirror of https://github.com/lianthony/NT4.0
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.
1033 lines
29 KiB
1033 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 1992-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
registry.c
|
|
|
|
Abstract:
|
|
|
|
Registry support for the video port driver.
|
|
|
|
Author:
|
|
|
|
Andre Vachon (andreva) 01-Mar-1992
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "dderror.h"
|
|
#include "ntos.h"
|
|
#include "pci.h"
|
|
#include "zwapi.h"
|
|
|
|
#include "ntddvdeo.h"
|
|
#include "video.h"
|
|
#include "videoprt.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,pOverrideConflict)
|
|
#pragma alloc_text(PAGE,VideoPortGetAccessRanges)
|
|
#pragma alloc_text(PAGE,pVideoPortReportResourceList)
|
|
#pragma alloc_text(PAGE,VideoPortVerifyAccessRanges)
|
|
#endif
|
|
|
|
|
|
BOOLEAN
|
|
pOverrideConflict(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
BOOLEAN bSetResources
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if the port driver should oerride the conflict int he registry.
|
|
|
|
bSetResources determines if the routine is checking the state for setting
|
|
the resources in the registry, or for cleaning them.
|
|
|
|
For example, if we are running basevideo and there is a conflict with the
|
|
vga, we want to override the conflict, but not clear the contents of
|
|
the registry.
|
|
|
|
Return Value:
|
|
|
|
TRUE if it should, FALSE if it should not.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
UNICODE_STRING unicodeString;
|
|
HANDLE handle;
|
|
|
|
//
|
|
// \Driver\Vga is for backwards compatibility since we do not have it
|
|
// anymore. It has become \Driver\VgaSave.
|
|
//
|
|
|
|
RtlInitUnicodeString(&unicodeString, L"\\Driver\\Vga");
|
|
|
|
if (!RtlCompareUnicodeString(&(DeviceExtension->DeviceObject->DriverObject->DriverName),
|
|
&unicodeString,
|
|
TRUE)) {
|
|
|
|
//
|
|
// Strings were equal - return SUCCESS
|
|
//
|
|
|
|
pVideoDebugPrint((0, "pOverrideConflict: found Vga string\n"));
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
RtlInitUnicodeString(&unicodeString, L"\\Driver\\VgaSave");
|
|
|
|
if (!RtlCompareUnicodeString(&(DeviceExtension->DeviceObject->DriverObject->DriverName),
|
|
&unicodeString,
|
|
TRUE)) {
|
|
//
|
|
// Return TRUE if we are just checking for confict (never want this
|
|
// driver to generate a conflict).
|
|
// We want to return TRUE only if we are not in basevideo since we
|
|
// only want to clear the resources if we are NOT in basevideo
|
|
// we are clearing the resources.
|
|
//
|
|
|
|
|
|
pVideoDebugPrint((0, "pOverrideConflict: found VgaSave string. Returning %d\n",
|
|
bSetResources));
|
|
|
|
return (bSetResources || (!VpBaseVideo));
|
|
|
|
|
|
} else {
|
|
|
|
RtlInitUnicodeString(&unicodeString,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DetectDisplay");
|
|
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&unicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
(HANDLE) NULL,
|
|
(PSECURITY_DESCRIPTOR) NULL);
|
|
|
|
if (!NT_SUCCESS(ZwOpenKey(&handle,
|
|
FILE_GENERIC_READ | SYNCHRONIZE,
|
|
&objectAttributes))) {
|
|
|
|
//
|
|
// We failed all checks, so we will report a conflict
|
|
//
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
pVideoDebugPrint((0, "pOverrideConflict: Display Detection Found\n"));
|
|
|
|
ZwClose(handle);
|
|
return TRUE;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
} // end pOverrideConflict()
|
|
|
|
|
|
VIDEOPORT_API
|
|
VP_STATUS
|
|
VideoPortGetAccessRanges(
|
|
PVOID HwDeviceExtension,
|
|
ULONG NumRequestedResources,
|
|
PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL,
|
|
ULONG NumAccessRanges,
|
|
PVIDEO_ACCESS_RANGE AccessRanges,
|
|
PVOID VendorId,
|
|
PVOID DeviceId,
|
|
PULONG Slot
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Walk the appropriate bus to get device information.
|
|
Search for the appropriate device ID.
|
|
Appropriate resources will be returned and automatically stored in the
|
|
resourcemap.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Points to the miniport driver's device extension.
|
|
|
|
NumRequestedResources - Number of entries in the RequestedResources array.
|
|
|
|
RequestedResources - Optional pointer to an array ofRequestedResources
|
|
the miniport driver wants to access.
|
|
|
|
NumAccessRanges - Maximum number of access ranges that can be returned
|
|
by the function.
|
|
|
|
AccessRanges - Array of access ranges that will be returned to the driver.
|
|
|
|
VendorId - Pointer to the vendor ID. On PCI, this is a pointer to a 16 bit
|
|
word.
|
|
|
|
DeviceId - Pointer to the Device ID. On PCI, this is a pointer to a 16 bit
|
|
word.
|
|
|
|
Slot - Pointer to the starting slot number for this search.
|
|
|
|
Return Value:
|
|
|
|
ERROR_MORE_DATA if the AccessRange structure is not large enough for the
|
|
PCI config info.
|
|
ERROR_DEV_NOT_EXIST is the card is not found.
|
|
|
|
NO_ERROR if the function succeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension =
|
|
deviceExtension = ((PDEVICE_EXTENSION) HwDeviceExtension) - 1;
|
|
|
|
PCI_SLOT_NUMBER slotData;
|
|
PCI_COMMON_CONFIG pciBuffer;
|
|
PPCI_COMMON_CONFIG pciData;
|
|
|
|
UNICODE_STRING unicodeString;
|
|
ULONG i;
|
|
ULONG j;
|
|
|
|
PCM_RESOURCE_LIST cmResourceList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
|
|
|
|
VP_STATUS status;
|
|
UCHAR bShare;
|
|
|
|
//
|
|
//
|
|
// typedef struct _PCI_SLOT_NUMBER {
|
|
// union {
|
|
// struct {
|
|
// ULONG DeviceNumber:5;
|
|
// ULONG FunctionNumber:3;
|
|
// ULONG Reserved:24;
|
|
// } bits;
|
|
// ULONG AsULONG;
|
|
// } u;
|
|
// } PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
|
|
//
|
|
|
|
slotData.u.AsULONG = 0;
|
|
pciData = (PPCI_COMMON_CONFIG)&pciBuffer;
|
|
|
|
//
|
|
// This is the miniport drivers slot. Allocate the
|
|
// resources.
|
|
//
|
|
|
|
RtlInitUnicodeString(&unicodeString, deviceExtension->DriverRegistryPath);
|
|
|
|
//
|
|
// Assert drivers do set those parameters properly
|
|
//
|
|
|
|
#if DBG
|
|
|
|
if ((NumRequestedResources == 0) != (RequestedResources == NULL)) {
|
|
|
|
pVideoDebugPrint((0, "VideoPortGetDeviceResources: Parameters for requested resource are inconsistent\n"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// An empty requested resource list means we want to automatic behavoir.
|
|
// Just call the HAL to get all the information
|
|
//
|
|
|
|
if (NumRequestedResources == 0) {
|
|
|
|
//
|
|
// Only PCI is supported for automatic querying
|
|
//
|
|
|
|
if (deviceExtension->AdapterInterfaceType == PCIBus) {
|
|
|
|
status = ERROR_DEV_NOT_EXIST;
|
|
|
|
//
|
|
// Look on each slot
|
|
//
|
|
|
|
while (*Slot < 32) {
|
|
|
|
slotData.u.bits.DeviceNumber = *Slot;
|
|
|
|
//
|
|
// Look at each function.
|
|
//
|
|
|
|
for (i= 0; i < 8; i++) {
|
|
|
|
slotData.u.bits.FunctionNumber = i;
|
|
|
|
if (HalGetBusData(PCIConfiguration,
|
|
deviceExtension->SystemIoBusNumber,
|
|
slotData.u.AsULONG,
|
|
pciData,
|
|
PCI_COMMON_HDR_LENGTH) == 0) {
|
|
|
|
//
|
|
// Out of functions. Go to next PCI bus.
|
|
//
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pciData->VendorID == PCI_INVALID_VENDORID) {
|
|
|
|
//
|
|
// No PCI device, or no more functions on device
|
|
// move to next PCI device.
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
if (pciData->VendorID != *((PUSHORT)VendorId) ||
|
|
pciData->DeviceID != *((PUSHORT)DeviceId)) {
|
|
|
|
//
|
|
// Not our PCI device. Try next device/function
|
|
//
|
|
|
|
continue;
|
|
}
|
|
#if 0
|
|
//
|
|
// This breaks my verite card !
|
|
// Andre
|
|
//
|
|
|
|
//
|
|
// If a PCI device is disabled, lets assume
|
|
// that it was disabled by the system, and not
|
|
// try to configure the card.
|
|
//
|
|
// The Command register will be zero if the
|
|
// card is disabled.
|
|
//
|
|
// BUGBUG:
|
|
//
|
|
// Is this really the right way to handle this?
|
|
//
|
|
|
|
if (pciData->Command == 0)
|
|
{
|
|
//
|
|
// Act as if we did not even see the card.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
#endif
|
|
if (NT_SUCCESS(HalAssignSlotResources(&unicodeString,
|
|
&VideoClassName,
|
|
deviceExtension->DeviceObject->DriverObject,
|
|
deviceExtension->DeviceObject,
|
|
PCIBus,
|
|
deviceExtension->SystemIoBusNumber,
|
|
slotData.u.AsULONG,
|
|
&cmResourceList))) {
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
} else {
|
|
|
|
//
|
|
// ToDo: Log this error.
|
|
//
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go to the next slot
|
|
//
|
|
|
|
if (status == NO_ERROR) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
(*Slot)++;
|
|
|
|
}
|
|
|
|
} // while()
|
|
|
|
} else {
|
|
|
|
//
|
|
// This is not a supported bus type.
|
|
//
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST requestedResources;
|
|
ULONG requestedResourceSize;
|
|
NTSTATUS ntStatus;
|
|
|
|
status = NO_ERROR;
|
|
|
|
//
|
|
// The caller has specified some resources.
|
|
// Lets call IoAssignResources with that and see what comes back.
|
|
//
|
|
|
|
requestedResourceSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
|
|
((NumRequestedResources - 1) *
|
|
sizeof(IO_RESOURCE_DESCRIPTOR));
|
|
|
|
requestedResources = ExAllocatePool(PagedPool, requestedResourceSize);
|
|
|
|
if (requestedResources) {
|
|
|
|
RtlZeroMemory(requestedResources, requestedResourceSize);
|
|
|
|
requestedResources->ListSize = requestedResourceSize;
|
|
requestedResources->InterfaceType = deviceExtension->AdapterInterfaceType;
|
|
requestedResources->BusNumber = deviceExtension->SystemIoBusNumber;
|
|
requestedResources->SlotNumber = Slot ? (*Slot) : -1;
|
|
requestedResources->AlternativeLists = 1;
|
|
|
|
requestedResources->List[0].Version = 1;
|
|
requestedResources->List[0].Revision = 1;
|
|
requestedResources->List[0].Count = NumRequestedResources;
|
|
|
|
RtlMoveMemory(&(requestedResources->List[0].Descriptors[0]),
|
|
RequestedResources,
|
|
NumRequestedResources * sizeof(IO_RESOURCE_DESCRIPTOR));
|
|
|
|
ntStatus = IoAssignResources(&unicodeString,
|
|
&VideoClassName,
|
|
deviceExtension->DeviceObject->DriverObject,
|
|
deviceExtension->DeviceObject,
|
|
requestedResources,
|
|
&cmResourceList);
|
|
|
|
ExFreePool(requestedResources);
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (status == NO_ERROR) {
|
|
|
|
//
|
|
// We now have a valid cmResourceList.
|
|
// Lets translate it back to access ranges so the driver
|
|
// only has to deal with one type of list.
|
|
//
|
|
|
|
//
|
|
// NOTE: The resources have already been reported at this point in
|
|
// time.
|
|
//
|
|
|
|
//
|
|
// Walk resource list to update configuration information.
|
|
//
|
|
|
|
for (i = 0, j = 0;
|
|
(i < cmResourceList->List->PartialResourceList.Count) &&
|
|
(status == NO_ERROR);
|
|
i++) {
|
|
|
|
//
|
|
// Get resource descriptor.
|
|
//
|
|
|
|
cmResourceDescriptor =
|
|
&cmResourceList->List->PartialResourceList.PartialDescriptors[i];
|
|
|
|
//
|
|
// Get the share disposition
|
|
//
|
|
|
|
if (cmResourceDescriptor->ShareDisposition == CmResourceShareShared) {
|
|
|
|
bShare = 1;
|
|
|
|
} else {
|
|
|
|
bShare = 0;
|
|
|
|
}
|
|
|
|
switch (cmResourceDescriptor->Type) {
|
|
|
|
case CmResourceTypePort:
|
|
case CmResourceTypeMemory:
|
|
|
|
|
|
// !!! what about sharing when you just do the default
|
|
// AssignResources ?
|
|
|
|
|
|
//
|
|
// common part
|
|
//
|
|
|
|
if (j == NumAccessRanges) {
|
|
|
|
status = ERROR_MORE_DATA;
|
|
break;
|
|
|
|
}
|
|
|
|
AccessRanges[j].RangeLength =
|
|
cmResourceDescriptor->u.Memory.Length;
|
|
AccessRanges[j].RangeStart =
|
|
cmResourceDescriptor->u.Memory.Start;
|
|
AccessRanges[j].RangeVisible = 0;
|
|
AccessRanges[j].RangeShareable = bShare;
|
|
|
|
//
|
|
// separate part
|
|
//
|
|
|
|
if (cmResourceDescriptor->Type == CmResourceTypePort) {
|
|
AccessRanges[j].RangeInIoSpace = 1;
|
|
} else {
|
|
AccessRanges[j].RangeInIoSpace = 0;
|
|
}
|
|
|
|
j++;
|
|
|
|
break;
|
|
|
|
case CmResourceTypeInterrupt:
|
|
|
|
deviceExtension->MiniportConfigInfo->BusInterruptVector =
|
|
cmResourceDescriptor->u.Interrupt.Vector;
|
|
deviceExtension->MiniportConfigInfo->BusInterruptLevel =
|
|
cmResourceDescriptor->u.Interrupt.Level;
|
|
deviceExtension->MiniportConfigInfo->InterruptShareable =
|
|
bShare;
|
|
|
|
break;
|
|
|
|
case CmResourceTypeDma:
|
|
|
|
deviceExtension->MiniportConfigInfo->DmaChannel =
|
|
cmResourceDescriptor->u.Dma.Channel;
|
|
deviceExtension->MiniportConfigInfo->DmaPort =
|
|
cmResourceDescriptor->u.Dma.Port;
|
|
deviceExtension->MiniportConfigInfo->DmaShareable =
|
|
bShare;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pVideoDebugPrint((0, "VideoPortGetAccessRanges: Unknown descriptor type %x\n",
|
|
cmResourceDescriptor->Type ));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Free the resource provided by the IO system.
|
|
//
|
|
|
|
ExFreePool(cmResourceList);
|
|
|
|
}
|
|
|
|
#if DBG
|
|
|
|
if (status == NO_ERROR)
|
|
{
|
|
//
|
|
// Indicates resources have been mapped properly
|
|
//
|
|
|
|
VPResourcesReported = TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
return status;
|
|
|
|
} // VideoPortGetDeviceResources()
|
|
|
|
|
|
NTSTATUS
|
|
pVideoPortReportResourceList(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
ULONG NumAccessRanges,
|
|
PVIDEO_ACCESS_RANGE AccessRanges,
|
|
PBOOLEAN Conflict
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a resource list which is used to query or report resource usage
|
|
in the system
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the miniport's driver device extension.
|
|
|
|
NumAccessRanges - Num of access ranges in the AccessRanges array.
|
|
|
|
AccessRanges - Pointer to an array of access ranges used by a miniport
|
|
driver.
|
|
|
|
Conflict - Determines whether or not a conflict occured.
|
|
|
|
Return Value:
|
|
|
|
Returns the final status of the operation
|
|
|
|
--*/
|
|
|
|
{
|
|
PCM_RESOURCE_LIST resourceList;
|
|
PCM_FULL_RESOURCE_DESCRIPTOR fullResourceDescriptor;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialResourceDescriptor;
|
|
ULONG listLength = 0;
|
|
ULONG size;
|
|
ULONG i;
|
|
NTSTATUS ntStatus;
|
|
BOOLEAN overrideConflict;
|
|
BOOLEAN bAddC0000 = FALSE;
|
|
VIDEO_ACCESS_RANGE arC0000;
|
|
|
|
//
|
|
// Create a resource list based on the information in the access range.
|
|
// and the miniport config info.
|
|
//
|
|
|
|
listLength = NumAccessRanges;
|
|
|
|
//
|
|
// Determine if we have DMA and interrupt resources to report
|
|
//
|
|
|
|
if (DeviceExtension->HwInterrupt &&
|
|
((DeviceExtension->MiniportConfigInfo->BusInterruptLevel != 0) ||
|
|
(DeviceExtension->MiniportConfigInfo->BusInterruptVector != 0)) ) {
|
|
|
|
listLength++;
|
|
}
|
|
|
|
if ((DeviceExtension->MiniportConfigInfo->DmaChannel) &&
|
|
(DeviceExtension->MiniportConfigInfo->DmaPort)) {
|
|
listLength++;
|
|
}
|
|
|
|
//
|
|
// Allocate upper bound.
|
|
//
|
|
|
|
resourceList = (PCM_RESOURCE_LIST)
|
|
ExAllocatePool(PagedPool,
|
|
sizeof(CM_RESOURCE_LIST) * 2 +
|
|
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * listLength);
|
|
|
|
//
|
|
// Return NULL if the structure could not be allocated.
|
|
// Otherwise, fill it out.
|
|
//
|
|
|
|
if (!resourceList) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
} else {
|
|
|
|
size = sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
|
|
resourceList->Count = 1;
|
|
|
|
fullResourceDescriptor = &(resourceList->List[0]);
|
|
fullResourceDescriptor->InterfaceType = DeviceExtension->AdapterInterfaceType;
|
|
fullResourceDescriptor->BusNumber = DeviceExtension->SystemIoBusNumber;
|
|
fullResourceDescriptor->PartialResourceList.Version = 0;
|
|
fullResourceDescriptor->PartialResourceList.Revision = 0;
|
|
fullResourceDescriptor->PartialResourceList.Count = 0;
|
|
|
|
//
|
|
// For each entry in the access range, fill in an entry in the
|
|
// resource list
|
|
//
|
|
|
|
partialResourceDescriptor =
|
|
&(fullResourceDescriptor->PartialResourceList.PartialDescriptors[0]);
|
|
|
|
for (i = 0; i < NumAccessRanges; i++, AccessRanges++) {
|
|
|
|
//
|
|
// In the case of the new HAL interface, report the C0000 address
|
|
// as being on the internal bus so that HalTranslateBusAddress
|
|
// succeeds properly.
|
|
//
|
|
|
|
if ((AccessRanges->RangeStart.LowPart == 0x000C0000) &&
|
|
(AccessRanges->RangeInIoSpace == 0) &&
|
|
(VpC0000Compatible == 2)) {
|
|
|
|
arC0000 = *AccessRanges;
|
|
bAddC0000 = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (AccessRanges->RangeInIoSpace) {
|
|
partialResourceDescriptor->Type = CmResourceTypePort;
|
|
partialResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
|
|
} else {
|
|
partialResourceDescriptor->Type = CmResourceTypeMemory;
|
|
partialResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
|
|
}
|
|
|
|
partialResourceDescriptor->ShareDisposition =
|
|
(AccessRanges->RangeShareable ?
|
|
CmResourceShareShared :
|
|
CmResourceShareDeviceExclusive);
|
|
|
|
partialResourceDescriptor->u.Memory.Start =
|
|
AccessRanges->RangeStart;
|
|
partialResourceDescriptor->u.Memory.Length =
|
|
AccessRanges->RangeLength;
|
|
|
|
//
|
|
// Increment the size for the new entry
|
|
//
|
|
|
|
size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
fullResourceDescriptor->PartialResourceList.Count += 1;
|
|
partialResourceDescriptor++;
|
|
}
|
|
|
|
//
|
|
// Fill in the entry for the interrupt if it was present.
|
|
//
|
|
|
|
if (DeviceExtension->HwInterrupt &&
|
|
((DeviceExtension->MiniportConfigInfo->BusInterruptLevel != 0) ||
|
|
(DeviceExtension->MiniportConfigInfo->BusInterruptVector != 0)) ) {
|
|
|
|
partialResourceDescriptor->Type = CmResourceTypeInterrupt;
|
|
|
|
partialResourceDescriptor->ShareDisposition =
|
|
(DeviceExtension->MiniportConfigInfo->InterruptShareable ?
|
|
CmResourceShareShared :
|
|
CmResourceShareDeviceExclusive);
|
|
|
|
partialResourceDescriptor->Flags = 0;
|
|
|
|
partialResourceDescriptor->u.Interrupt.Level =
|
|
DeviceExtension->MiniportConfigInfo->BusInterruptLevel;
|
|
partialResourceDescriptor->u.Interrupt.Vector =
|
|
DeviceExtension->MiniportConfigInfo->BusInterruptVector;
|
|
|
|
partialResourceDescriptor->u.Interrupt.Affinity = 0;
|
|
|
|
//
|
|
// Increment the size for the new entry
|
|
//
|
|
|
|
size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
fullResourceDescriptor->PartialResourceList.Count += 1;
|
|
partialResourceDescriptor++;
|
|
}
|
|
|
|
//
|
|
// Fill in the entry for the DMA channel.
|
|
//
|
|
|
|
if ((DeviceExtension->MiniportConfigInfo->DmaChannel) &&
|
|
(DeviceExtension->MiniportConfigInfo->DmaPort)) {
|
|
|
|
partialResourceDescriptor->Type = CmResourceTypeDma;
|
|
|
|
partialResourceDescriptor->ShareDisposition =
|
|
(DeviceExtension->MiniportConfigInfo->DmaShareable ?
|
|
CmResourceShareShared :
|
|
CmResourceShareDeviceExclusive);
|
|
|
|
partialResourceDescriptor->Flags = 0;
|
|
|
|
partialResourceDescriptor->u.Dma.Channel =
|
|
DeviceExtension->MiniportConfigInfo->DmaChannel;
|
|
partialResourceDescriptor->u.Dma.Port =
|
|
DeviceExtension->MiniportConfigInfo->DmaPort;
|
|
|
|
partialResourceDescriptor->u.Dma.Reserved1 = 0;
|
|
|
|
//
|
|
// Increment the size for the new entry
|
|
//
|
|
|
|
size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
fullResourceDescriptor->PartialResourceList.Count += 1;
|
|
partialResourceDescriptor++;
|
|
}
|
|
|
|
if (bAddC0000) {
|
|
|
|
if (partialResourceDescriptor !=
|
|
&(fullResourceDescriptor->PartialResourceList.PartialDescriptors[0])) {
|
|
|
|
fullResourceDescriptor = (PVOID) partialResourceDescriptor;
|
|
|
|
resourceList->Count = 2;
|
|
fullResourceDescriptor->InterfaceType = Internal;
|
|
fullResourceDescriptor->BusNumber = 0;
|
|
fullResourceDescriptor->PartialResourceList.Version = 0;
|
|
fullResourceDescriptor->PartialResourceList.Revision = 0;
|
|
fullResourceDescriptor->PartialResourceList.Count = 0;
|
|
|
|
partialResourceDescriptor = (&fullResourceDescriptor->PartialResourceList.PartialDescriptors[0]);
|
|
size += sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
|
|
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
}
|
|
|
|
partialResourceDescriptor->Type = CmResourceTypeMemory;
|
|
partialResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
|
|
|
|
partialResourceDescriptor->ShareDisposition =
|
|
(arC0000.RangeShareable ?
|
|
CmResourceShareShared :
|
|
CmResourceShareDeviceExclusive);
|
|
|
|
partialResourceDescriptor->u.Memory.Start = arC0000.RangeStart;
|
|
partialResourceDescriptor->u.Memory.Length = arC0000.RangeLength;
|
|
|
|
|
|
//
|
|
// Increment the size for the new entry
|
|
//
|
|
|
|
size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
fullResourceDescriptor->PartialResourceList.Count += 1;
|
|
partialResourceDescriptor++;
|
|
|
|
}
|
|
|
|
//
|
|
// Determine if the conflict should be overriden.
|
|
//
|
|
|
|
//
|
|
// If we are loading the VGA, do not generate an error if it conflicts
|
|
// with another driver.
|
|
//
|
|
|
|
|
|
overrideConflict = pOverrideConflict(DeviceExtension, TRUE);
|
|
|
|
#if DBG
|
|
if (overrideConflict) {
|
|
|
|
pVideoDebugPrint((2, "We are checking the vga driver resources\n"));
|
|
|
|
} else {
|
|
|
|
pVideoDebugPrint((2, "We are NOT checking vga driver resources\n"));
|
|
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Report the resources.
|
|
//
|
|
|
|
ntStatus = IoReportResourceUsage(&VideoClassName,
|
|
DeviceExtension->DeviceObject->DriverObject,
|
|
NULL,
|
|
0L,
|
|
DeviceExtension->DeviceObject,
|
|
resourceList,
|
|
size,
|
|
overrideConflict,
|
|
Conflict);
|
|
|
|
ExFreePool(resourceList);
|
|
|
|
//
|
|
// This is for hive compatibility back when we have the VGA driver
|
|
// as opposed to VgaSave.
|
|
// The Vga also cleans up the resource automatically.
|
|
//
|
|
|
|
//
|
|
// If we tried to override the conflict, let's take a look a what
|
|
// we want to do with the result
|
|
//
|
|
|
|
if ((NT_SUCCESS(ntStatus)) &&
|
|
overrideConflict &&
|
|
*Conflict) {
|
|
|
|
//
|
|
// For cases like DetectDisplay, a conflict is bad and we do
|
|
// want to fail.
|
|
//
|
|
// In the case of Basevideo, a conflict is possible. But we still
|
|
// want to load the VGA anyways. Return success and reset the
|
|
// conflict flag !
|
|
//
|
|
// pOverrideConflict with the FALSE flag will check that.
|
|
//
|
|
|
|
if (pOverrideConflict(DeviceExtension, FALSE)) {
|
|
|
|
ULONG emptyResourceList = 0;
|
|
BOOLEAN ignore;
|
|
|
|
size = sizeof(ULONG);
|
|
|
|
pVideoDebugPrint((1, "videoprt: Removing the conflicting resources\n"));
|
|
|
|
ntStatus = IoReportResourceUsage(&VideoClassName,
|
|
DeviceExtension->DeviceObject->DriverObject,
|
|
NULL,
|
|
0L,
|
|
DeviceExtension->DeviceObject,
|
|
(PCM_RESOURCE_LIST)&emptyResourceList,
|
|
size,
|
|
overrideConflict,
|
|
&ignore);
|
|
|
|
//
|
|
// return a conflict to the vga driver so it does not load.
|
|
//
|
|
|
|
ntStatus = STATUS_CONFLICTING_ADDRESSES;
|
|
|
|
} else {
|
|
|
|
*Conflict = FALSE;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
} // end pVideoPortBuildResourceList()
|
|
|
|
|
|
VP_STATUS
|
|
VideoPortVerifyAccessRanges(
|
|
PVOID HwDeviceExtension,
|
|
ULONG NumAccessRanges,
|
|
PVIDEO_ACCESS_RANGE AccessRanges
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
VideoPortVerifyAccessRanges
|
|
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Points to the miniport driver's device extension.
|
|
|
|
NumAccessRanges - Number of entries in the AccessRanges array.
|
|
|
|
AccessRanges - Pointer to an array of AccessRanges the miniport driver
|
|
wants to access.
|
|
|
|
Return Value:
|
|
|
|
ERROR_INVALID_PARAMETER in an error occured
|
|
NO_ERROR if the call completed successfully
|
|
|
|
Environment:
|
|
|
|
This routine cannot be called from a miniport routine synchronized with
|
|
VideoPortSynchronizeRoutine or from an ISR.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
BOOLEAN conflict;
|
|
PDEVICE_EXTENSION deviceExtension =
|
|
((PDEVICE_EXTENSION)HwDeviceExtension) - 1;
|
|
|
|
status = pVideoPortReportResourceList(deviceExtension,
|
|
NumAccessRanges,
|
|
AccessRanges,
|
|
&conflict);
|
|
|
|
if ((NT_SUCCESS(status)) && (!conflict)) {
|
|
|
|
#if DBG
|
|
|
|
//
|
|
// Indicates resources have been mapped properly
|
|
//
|
|
|
|
VPResourcesReported = TRUE;
|
|
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
|
|
} else {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
} // end VideoPortVerifyAccessRanges()
|