NT4/private/ntos/video/port/registry.c
2020-09-30 17:12:29 +02:00

1034 lines
29 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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()