/*++ Copyright (c) 1997 Microsoft Corporation Module Name: ixpnpdrv.c Abstract: Implements functionality necessary for the HAL to become a PnP-style device driver after system initialization. This is done so that the HAL can enumerate the PCI busses in the way that the PnP stuff expects. Author: Jake Oshins (jakeo) 27-Jan-1997 Environment: Kernel mode only. Revision History: --*/ #include "halp.h" #include "exboosts.h" #include "wchar.h" #include "pci.h" #include "pcip.h" #if defined(NT_UP) && defined(APIC_HAL) #include "apic.inc" #include "pcmp_nt.inc" #endif #ifdef ALLOC_DATA_PRAGMA #pragma const_seg("PAGECONST") #endif // ALLOC_DATA_PRAGMA //Instantiate the guids here only. #include "initguid.h" #include "wdmguid.h" #ifdef ALLOC_DATA_PRAGMA #pragma const_seg() #endif // ALLOC_DATA_PRAGMA #ifdef WANT_IRQ_ROUTING // Pci Irq Routing. #include "ixpciir.h" #endif WCHAR rgzTranslated[] = L".Translated"; WCHAR rgzBusTranslated[] = L".Bus.Translated"; WCHAR rgzResourceMap[] = L"\\REGISTRY\\MACHINE\\HARDWARE\\RESOURCEMAP"; #if DBG ULONG HalDebug = 0; #endif extern WCHAR rgzTranslated[]; extern WCHAR rgzBusTranslated[]; extern WCHAR rgzResourceMap[]; extern WCHAR HalHardwareIdString[]; #if defined(NT_UP) && defined(APIC_HAL) extern WCHAR MpHalHardwareIdString[]; #endif extern struct HalpMpInfo HalpMpInfoTable; typedef enum { Hal = 0x80, PciDriver, IsaPnpDriver, McaDriver } PDO_TYPE; typedef enum { PdoExtensionType = 0xc0, FdoExtensionType } EXTENSION_TYPE; typedef struct _PDO_EXTENSION *PPDO_EXTENSION; typedef struct _FDO_EXTENSION *PFDO_EXTENSION; typedef struct _PDO_EXTENSION{ EXTENSION_TYPE ExtensionType; PDEVICE_OBJECT Next; PDEVICE_OBJECT PhysicalDeviceObject; PFDO_EXTENSION ParentFdoExtension; PDO_TYPE PdoType; ULONG BusNumber; ULONG MaxSubordinateBusNumber; PBUS_HANDLER Bus; LONG InterfaceReferenceCount; } PDO_EXTENSION, *PPDO_EXTENSION; #define ASSERT_PDO_EXTENSION(x) ASSERT((x)->ExtensionType == PdoExtensionType ); typedef struct _FDO_EXTENSION{ EXTENSION_TYPE ExtensionType; PDEVICE_OBJECT ChildPdoList; PDEVICE_OBJECT PhysicalDeviceObject; // PDO passed into AddDevice() PDEVICE_OBJECT FunctionalDeviceObject; PDEVICE_OBJECT AttachedDeviceObject; ULONG BusCount; } FDO_EXTENSION, *PFDO_EXTENSION; #define ASSERT_FDO_EXTENSION(x) ASSERT((x)->ExtensionType == FdoExtensionType ); INT_ROUTE_INTERFACE_STANDARD PciIrqRoutingInterface = {0}; NTSTATUS HalpDriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS HalpAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ); NTSTATUS HalpDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ); NTSTATUS HalpDispatchPower( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ); NTSTATUS HalpDispatchWmi( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ); VOID HalpCompleteRequest( IN OUT PIRP Irp, IN NTSTATUS Status, IN ULONG Information ); NTSTATUS HalpQueryDeviceRelations( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE RelationType, OUT PDEVICE_RELATIONS *DeviceRelations ); NTSTATUS HalpQueryIdPdo( IN PDEVICE_OBJECT PdoExtension, IN BUS_QUERY_ID_TYPE IdType, IN OUT PWSTR *BusQueryId ); NTSTATUS HalpQueryIdFdo( IN PDEVICE_OBJECT PdoExtension, IN BUS_QUERY_ID_TYPE IdType, IN OUT PWSTR *BusQueryId ); NTSTATUS HalpQueryCapabilities( IN PDEVICE_OBJECT Pdo, IN PDEVICE_CAPABILITIES Capabilities ); NTSTATUS HalpQueryDeviceText( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_TEXT_TYPE IdType, IN OUT PWSTR *BusQueryId ); NTSTATUS HalpQueryInterface( IN PDEVICE_OBJECT DeviceObject, IN LPCGUID InterfaceType, IN USHORT Version, IN PVOID InterfaceSpecificData, IN ULONG InterfaceBufferSize, IN OUT PINTERFACE Interface, IN OUT PULONG Length ); #ifdef WANT_IRQ_ROUTING NTSTATUS HalpQueryInterfaceFdo( IN PDEVICE_OBJECT DeviceObject, IN LPCGUID InterfaceType, IN USHORT Version, IN PVOID InterfaceSpecificData, IN ULONG InterfaceBufferSize, IN OUT PINTERFACE Interface, IN OUT PULONG Length ); #endif NTSTATUS HalpQueryResources( PDEVICE_OBJECT DeviceObject, PCM_RESOURCE_LIST *Resources ); NTSTATUS HalpQueryResourceRequirements( PDEVICE_OBJECT DeviceObject, PIO_RESOURCE_REQUIREMENTS_LIST *Requirements ); NTSTATUS HalpRemoveAssignedResources( PBUS_HANDLER Bus ); VOID HalpMarkNonAcpiHal( VOID ); // // Define the PNP interface functions. // VOID HalPnpInterfaceReference( PVOID Context ); VOID HalPnpInterfaceDereference( PVOID Context ); BOOLEAN HalPnpTranslateBusAddress( IN PVOID Context, IN PHYSICAL_ADDRESS BusAddress, IN ULONG Length, IN OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress ); struct _DMA_ADAPTER * HalPnpGetDmaAdapter( IN PVOID Context, IN struct _DEVICE_DESCRIPTION *DeviceDescriptor, OUT PULONG NumberOfMapRegisters ); ULONG HalPnpReadConfig( IN PVOID Context, IN ULONG Slot, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ); ULONG HalPnpWriteConfig( IN PVOID Context, IN ULONG Slot, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ); NTSTATUS HalpGetPciInterfaces( IN PDEVICE_OBJECT PciPdo ); #ifdef APIC_HAL NTSTATUS HalpPci2MpsBusNumber( IN UCHAR PciBusNumber, OUT UCHAR *MpsBusNumber ); BOOLEAN HalpMpsBusIsRootBus( IN UCHAR MpsBus ); #endif #define PCI_HAL_DRIVER_NAME L"\\Driver\\PCI_HAL" #define ISA_HAL_DRIVER_NAME L"\\Driver\\ISA_HAL" #define MCA_HAL_DRIVER_NAME L"\\Driver\\MCA_HAL" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, HaliInitPnpDriver) #pragma alloc_text(PAGE, HalpDriverEntry) #pragma alloc_text(PAGE, HalpAddDevice) #pragma alloc_text(PAGE, HalpDispatchPnp) #pragma alloc_text(PAGELK, HalpDispatchPower) #pragma alloc_text(PAGE, HalpDispatchWmi) #pragma alloc_text(PAGE, HalpQueryDeviceRelations) #pragma alloc_text(PAGE, HalpQueryIdPdo) #pragma alloc_text(PAGE, HalpQueryIdFdo) #pragma alloc_text(PAGE, HalpQueryCapabilities) #pragma alloc_text(PAGE, HalpQueryInterface) #ifdef WANT_IRQ_ROUTING #pragma alloc_text(PAGE, HalpQueryInterfaceFdo) #endif #pragma alloc_text(PAGE, HalpQueryDeviceText) #pragma alloc_text(PAGE, HalpQueryResources) #pragma alloc_text(PAGE, HalpQueryResourceRequirements) #pragma alloc_text(PAGE, HalpRemoveAssignedResources) #pragma alloc_text(PAGE, HalpMarkNonAcpiHal) #pragma alloc_text(INIT, HalpMarkChipsetDecode) #pragma alloc_text(PAGE, HalpOpenRegistryKey) #pragma alloc_text(PAGE, HalpGetPciInterfaces) #pragma alloc_text(PAGE, HalPnpInterfaceDereference) #endif PDRIVER_OBJECT HalpDriverObject; NTSTATUS HaliInitPnpDriver( VOID ) /*++ Routine Description: This routine starts the process of making the HAL into a "driver," which is necessary because we need to enumerate a Plug and Play PDO for the PCI driver and ISAPNP driver. Arguments: None. Return Value: NTSTATUS. --*/ { UNICODE_STRING DriverName; NTSTATUS Status; PAGED_CODE(); // // For different bus pdo, we will use different hal name such that // it is less confusion. // if (HalpHandlerForBus (PCIBus, 0)) { RtlInitUnicodeString( &DriverName, PCI_HAL_DRIVER_NAME ); } else if (HalpHandlerForBus(MicroChannel, 0)) { RtlInitUnicodeString( &DriverName, MCA_HAL_DRIVER_NAME ); } else { RtlInitUnicodeString( &DriverName, ISA_HAL_DRIVER_NAME ); } Status = IoCreateDriver( &DriverName, HalpDriverEntry ); // // John Vert (jvert) 7/23/1998 // There is a value in the registry that the ACPI HAL sets to disable // the firmware mapper. Unfortunately this value is persistent. So if // you have an ACPI machine and "upgrade" it to a non-ACPI machine, the // value is still present. Workaround here is to set the value to zero. // HalpMarkNonAcpiHal(); if (!NT_SUCCESS( Status )) { ASSERT( NT_SUCCESS( Status )); return Status; } return STATUS_SUCCESS; } NTSTATUS HalpDriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: This is the callback function when we call IoCreateDriver to create a PnP Driver Object. In this function, we need to remember the DriverObject. Arguments: DriverObject - Pointer to the driver object created by the system. RegistryPath - is NULL. Return Value: STATUS_SUCCESS --*/ { NTSTATUS Status; PDEVICE_OBJECT detectedDeviceObject = NULL; PAGED_CODE(); // // File the pointer to our driver object away // HalpDriverObject = DriverObject; // // Fill in the driver object // DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE) HalpAddDevice; DriverObject->MajorFunction[ IRP_MJ_PNP ] = HalpDispatchPnp; DriverObject->MajorFunction[ IRP_MJ_POWER ] = HalpDispatchPower; DriverObject->MajorFunction[ IRP_MJ_SYSTEM_CONTROL ] = HalpDispatchWmi; Status = IoReportDetectedDevice(DriverObject, InterfaceTypeUndefined, -1, -1, NULL, NULL, FALSE, &detectedDeviceObject); ASSERT( detectedDeviceObject != NULL ); if (!(NT_SUCCESS(Status))) { HalPrint(("IoReportDetectedDevice failed")); return Status; } Status = HalpAddDevice(DriverObject, detectedDeviceObject); return Status; } NTSTATUS HalpAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ) /*++ Routine Description: This routine handles AddDevice for an madeup PDO device. Arguments: DriverObject - Pointer to our pseudo driver object. DeviceObject - Pointer to the device object for which this requestapplies. Return Value: NT Status. --*/ { PDEVICE_OBJECT FunctionalDeviceObject; PDEVICE_OBJECT ChildDeviceObject; PDEVICE_OBJECT AttachedDevice; NTSTATUS Status; PFDO_EXTENSION FdoExtension; PPDO_EXTENSION PdoExtension; PDEVICE_OBJECT Pdo2; ULONG BusNumber; ULONG BusCount = 0; PBUS_HANDLER Bus; WCHAR Buffer[40]; UNICODE_STRING Unicode; PDO_TYPE PdoType; UCHAR MpsBusNumber; PAGED_CODE(); // // We've been given the PhysicalDeviceObject. Create the // FunctionalDeviceObject. Our FDO will be nameless. // Status = IoCreateDevice( DriverObject, // our driver object sizeof(FDO_EXTENSION), // size of our extension NULL, // our name FILE_DEVICE_BUS_EXTENDER, // device type 0, // device characteristics FALSE, // not exclusive &FunctionalDeviceObject // store new device object here ); if( !NT_SUCCESS( Status )){ DbgBreakPoint(); return Status; } // // Fill in the FDO extension // FdoExtension = (PFDO_EXTENSION) FunctionalDeviceObject->DeviceExtension; FdoExtension->ExtensionType = FdoExtensionType; FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject; FdoExtension->FunctionalDeviceObject = FunctionalDeviceObject; FdoExtension->ChildPdoList = NULL; // // Now attach to the PDO we were given. // AttachedDevice = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject ); if (AttachedDevice == NULL) { HalPrint(("Couldn't attach")); // // Couldn't attach. Delete the FDO. // IoDeleteDevice( FunctionalDeviceObject ); return STATUS_NO_SUCH_DEVICE; } FdoExtension->AttachedDeviceObject = AttachedDevice; // // Clear the device initializing flag. // FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; // // Find any child PCI busses. // for ( BusNumber = 0; Bus = HaliReferenceHandlerForBus(PCIBus, BusNumber); BusNumber++ ) { #ifdef APIC_HAL Status = HalpPci2MpsBusNumber((UCHAR)BusNumber, &MpsBusNumber); if (NT_SUCCESS(Status)) { if (!HalpMpsBusIsRootBus(MpsBusNumber)) { // // This is not a root PCI bus, so skip it. // continue; } } #endif if (Bus->ParentHandler != NULL && Bus->ParentHandler->InterfaceType == PCIBus) { // // Skip bridges. // HaliDereferenceBusHandler( Bus ); continue; } // // Remove the system resoruces from the range lists. // Status = HalpRemoveAssignedResources( Bus ); if (!NT_SUCCESS(Status)) { HaliDereferenceBusHandler( Bus ); return Status; } _snwprintf( Buffer, sizeof(Buffer) / sizeof(Buffer[0]), L"\\Device\\Hal Pci %d", BusCount ); RtlInitUnicodeString( &Unicode, Buffer ); // // Next, create a PDO for the PCI driver. // Status = IoCreateDevice( DriverObject, // our driver object sizeof(PDO_EXTENSION), // size of our extension &Unicode, // our name FILE_DEVICE_BUS_EXTENDER, // device type 0, // device characteristics FALSE, // not exclusive &ChildDeviceObject // store new device object here ); if (!NT_SUCCESS(Status)) { HaliDereferenceBusHandler( Bus ); return Status; } // // Fill in the PDO extension // PdoExtension = (PPDO_EXTENSION) ChildDeviceObject->DeviceExtension; PdoExtension->ExtensionType = PdoExtensionType; PdoExtension->PhysicalDeviceObject = ChildDeviceObject; PdoExtension->ParentFdoExtension = FdoExtension; PdoExtension->PdoType = PciDriver; PdoExtension->BusNumber = BusNumber; PdoExtension->MaxSubordinateBusNumber = 0xff; // correct value later PdoExtension->Bus = Bus; BusCount++; // // Record this as a child of the HAL. Add new childern at the // end of the list. // PdoExtension->Next = NULL; if (FdoExtension->ChildPdoList == NULL) { FdoExtension->ChildPdoList = ChildDeviceObject; } else { for (Pdo2 = FdoExtension->ChildPdoList; ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next != NULL; Pdo2 = ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next); ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next = ChildDeviceObject; } // // Clear the device initializing flag. // ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; } // // Now loop through all the children PDOs making sure that // the MaxSubordinateBusNumbers are reasonable. This loop // assumes that the list is sorted by BusNumber. // Pdo2 = FdoExtension->ChildPdoList; while (Pdo2) { if (!((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next) { // // There is no next Pdo extension, which means that // this bus represents the last root bus, which means // that we can leave its subordinate bus number at 0xff. // break; } if (((PPDO_EXTENSION) Pdo2->DeviceExtension)->MaxSubordinateBusNumber >= ((PPDO_EXTENSION) ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next->DeviceExtension)->BusNumber) { // // Set the subordinate bus number at one less than the bus number of the // next root bus. // ((PPDO_EXTENSION)Pdo2->DeviceExtension)->MaxSubordinateBusNumber = ((PPDO_EXTENSION) ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next->DeviceExtension)->BusNumber - 1; } Pdo2 = ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next; } FdoExtension->BusCount = BusCount; if (BusCount == 0) { Bus = HaliReferenceHandlerForBus(Isa, 0); if (!Bus) { Bus = HaliReferenceHandlerForBus(Eisa, 0); } if (Bus) { RtlInitUnicodeString( &Unicode, L"\\Device\\Hal Isa 0" ); PdoType = IsaPnpDriver; } else { Bus = HaliReferenceHandlerForBus(MicroChannel, 0); ASSERT(Bus); RtlInitUnicodeString( &Unicode, L"\\Device\\Hal Mca 0" ); PdoType = McaDriver; } if (Bus) { // // Next, create a PDO for the PCI driver. // Status = IoCreateDevice( DriverObject, // our driver object sizeof(PDO_EXTENSION), // size of our extension &Unicode, // our name FILE_DEVICE_BUS_EXTENDER, // device type 0, // device characteristics FALSE, // not exclusive &ChildDeviceObject // store new device object here ); if (!NT_SUCCESS(Status)) { return Status; } // // Fill in the PDO extension // PdoExtension = (PPDO_EXTENSION) ChildDeviceObject->DeviceExtension; PdoExtension->ExtensionType = PdoExtensionType; PdoExtension->PhysicalDeviceObject = ChildDeviceObject; PdoExtension->ParentFdoExtension = FdoExtension; PdoExtension->BusNumber = 0; PdoExtension->MaxSubordinateBusNumber = 0; PdoExtension->Bus = Bus; PdoExtension->PdoType = PdoType; // // Record this as a child of the HAL // PdoExtension->Next = FdoExtension->ChildPdoList; FdoExtension->ChildPdoList = ChildDeviceObject; FdoExtension->BusCount = 1; // // Clear the device initializing flag. // ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; } } return STATUS_SUCCESS; } NTSTATUS HalpPassIrpFromFdoToPdo( PDEVICE_OBJECT DeviceObject, PIRP Irp ) /*++ Description: Given an FDO, pass the IRP to the next device object in the device stack. This is the PDO if there are no lower level filters. Arguments: DeviceObject - the Fdo Irp - the request Return Value: Returns the result from calling the next level. --*/ { PIO_STACK_LOCATION irpSp; // our stack location PIO_STACK_LOCATION nextIrpSp; // next guy's PFDO_EXTENSION fdoExtension; HalPrint(("PassIrp ...")); // // Get the pointer to the device extension. // fdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension; IoSkipCurrentIrpStackLocation(Irp); // // Call the PDO driver with the request. // return IoCallDriver(fdoExtension->AttachedDeviceObject ,Irp); } NTSTATUS HalpDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) /*++ Routine Description: This routine handles all IRP_MJ_PNP_POWER IRPs for madeup PDO device. Arguments: DeviceObject - Pointer to the device object for which this IRP applies. Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch. Return Value: NT status. --*/ { PIO_STACK_LOCATION irpSp; NTSTATUS Status; ULONG length; DEVICE_RELATION_TYPE relationType; EXTENSION_TYPE extensionType; BOOLEAN passDown; #if DBG PUCHAR objectTypeString; #endif //DBG PPDO_EXTENSION pdoExtension; PAGED_CODE(); pdoExtension = (PPDO_EXTENSION)DeviceObject->DeviceExtension; extensionType = ((PFDO_EXTENSION)pdoExtension)->ExtensionType; // // Get a pointer to our stack location and take appropriate action based // on the minor function. // irpSp = IoGetCurrentIrpStackLocation(Irp); switch (extensionType) { case PdoExtensionType: #if DBG objectTypeString = "PDO"; #endif //DBG switch (irpSp->MinorFunction) { case IRP_MN_START_DEVICE: HalPrint(("(%s) Start_Device Irp received", objectTypeString)); Status = STATUS_SUCCESS; // // If we are starting a PCI PDO, then we want to // collect a little bit of information from the PCI driver. // if (pdoExtension->PdoType == PciDriver) { Status = HalpGetPciInterfaces(DeviceObject); ASSERT(NT_SUCCESS(Status)); if (NT_SUCCESS(Status)) { PciIrqRoutingInterface.InterfaceReference(PciIrqRoutingInterface.Context); #ifdef WANT_IRQ_ROUTING // // Initialize Pci Irq Routing. // HalpPciIrqRoutingInfo.PciInterface = &PciIrqRoutingInterface; if (NT_SUCCESS(HalpInitPciIrqRouting(&HalpPciIrqRoutingInfo))) { HalPrint(("Pci Irq Routing initialized successfully!")); } else { HalPrint(("No Pci Irq routing on this system!")); } #endif } else { RtlZeroMemory(&PciIrqRoutingInterface, sizeof(INT_ROUTE_INTERFACE_STANDARD)); } } break; case IRP_MN_QUERY_STOP_DEVICE: HalPrint(("(%s) Query_Stop_Device Irp received", objectTypeString)); Status = STATUS_SUCCESS; break; case IRP_MN_CANCEL_STOP_DEVICE: HalPrint(("(%s) Cancel_Stop_Device Irp received", objectTypeString)); Status = STATUS_SUCCESS; break; case IRP_MN_STOP_DEVICE: HalPrint(("(%s) Stop_Device Irp received", objectTypeString)); // // If we get a stop device request for a PDO, we simply // return success. // Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_RESOURCES: HalPrint(("(%s) Query_Resources Irp received", objectTypeString)); Status = HalpQueryResources(DeviceObject, (PCM_RESOURCE_LIST *)&Irp->IoStatus.Information); Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: HalPrint(("(%s) Query_Resource_Requirements Irp received", objectTypeString)); Status = HalpQueryResourceRequirements(DeviceObject, (PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->IoStatus.Information); break; case IRP_MN_QUERY_REMOVE_DEVICE: HalPrint(("(%s) Query_Remove_device Irp for %x", objectTypeString, DeviceObject)); Status = STATUS_UNSUCCESSFUL; break; case IRP_MN_CANCEL_REMOVE_DEVICE: HalPrint(("(%s) Cancel_Remove_device Irp for %x", objectTypeString, DeviceObject)); Status = STATUS_SUCCESS; break; case IRP_MN_REMOVE_DEVICE: HalPrint(("(%s) Remove_device Irp for %x", objectTypeString, DeviceObject)); if ((((PPDO_EXTENSION)(DeviceObject->DeviceExtension))->PdoType == PciDriver) && (PciIrqRoutingInterface.InterfaceReference != NULL)) { PciIrqRoutingInterface.InterfaceDereference(PciIrqRoutingInterface.Context); } Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_DEVICE_RELATIONS: HalPrint(("(%s) Query_Device_Relations Irp received", objectTypeString)); relationType = irpSp->Parameters.QueryDeviceRelations.Type; Status = HalpQueryDeviceRelations(DeviceObject, relationType, (PDEVICE_RELATIONS*)&Irp->IoStatus.Information); break; case IRP_MN_QUERY_DEVICE_TEXT: HalPrint(("(%s) Query Device Text Irp received", objectTypeString)); Status = HalpQueryDeviceText(DeviceObject, irpSp->Parameters.QueryDeviceText.DeviceTextType, (PWSTR*)&Irp->IoStatus.Information); break; case IRP_MN_QUERY_ID: HalPrint(("(%s) Query_Id Irp received", objectTypeString)); Status = HalpQueryIdPdo(DeviceObject, irpSp->Parameters.QueryId.IdType, (PWSTR*)&Irp->IoStatus.Information); break; case IRP_MN_QUERY_INTERFACE: HalPrint(("(%s) Query_Interface Irp received", objectTypeString)); Status = HalpQueryInterface( DeviceObject, irpSp->Parameters.QueryInterface.InterfaceType, irpSp->Parameters.QueryInterface.Version, irpSp->Parameters.QueryInterface.InterfaceSpecificData, irpSp->Parameters.QueryInterface.Size, irpSp->Parameters.QueryInterface.Interface, &Irp->IoStatus.Information ); break; case IRP_MN_QUERY_CAPABILITIES: HalPrint(("(%s) Query_Capabilities Irp received", objectTypeString)); Status = HalpQueryCapabilities(DeviceObject, irpSp->Parameters.DeviceCapabilities.Capabilities); break; case IRP_MN_DEVICE_USAGE_NOTIFICATION: HalPrint(("(%s) Device_Usage_Notification Irp received", objectTypeString)); Status = STATUS_SUCCESS; break; default: HalPrint(("(%s) Unsupported Irp (%d) received", objectTypeString, irpSp->MinorFunction)); Status = STATUS_NOT_SUPPORTED ; break; } break; // end PDO cases case FdoExtensionType: #if DBG objectTypeString = "FDO"; #endif //DBG passDown = TRUE; switch (irpSp->MinorFunction){ case IRP_MN_QUERY_DEVICE_RELATIONS: HalPrint(("(%s) Query_Device_Relations Irp received", objectTypeString)); relationType = irpSp->Parameters.QueryDeviceRelations.Type; Status = HalpQueryDeviceRelations(DeviceObject, relationType, (PDEVICE_RELATIONS*)&Irp->IoStatus.Information); break; case IRP_MN_QUERY_ID: HalPrint(("(%s) Query_Id Irp received", objectTypeString)); Status = HalpQueryIdFdo(DeviceObject, irpSp->Parameters.QueryId.IdType, (PWSTR*)&Irp->IoStatus.Information); break; #ifdef WANT_IRQ_ROUTING case IRP_MN_QUERY_INTERFACE: HalPrint(("(%s) Query_Interface Irp received", objectTypeString)); Status = HalpQueryInterfaceFdo( DeviceObject, irpSp->Parameters.QueryInterface.InterfaceType, irpSp->Parameters.QueryInterface.Version, irpSp->Parameters.QueryInterface.InterfaceSpecificData, irpSp->Parameters.QueryInterface.Size, irpSp->Parameters.QueryInterface.Interface, &Irp->IoStatus.Information ); break; #endif default: // // Ignore any PNP Irps unknown by the FDO but allow them // down to the PDO. // Status = STATUS_NOT_SUPPORTED ; break; } if (passDown && (NT_SUCCESS(Status) || (Status == STATUS_NOT_SUPPORTED))) { // // Pass FDO IRPs down to the PDO. // // Set Irp status first. // if (Status != STATUS_NOT_SUPPORTED) { Irp->IoStatus.Status = Status; } HalPrint(("(%s) Passing down Irp (%x)", objectTypeString, irpSp->MinorFunction)); return HalpPassIrpFromFdoToPdo(DeviceObject, Irp); } break; // end FDO cases default: HalPrint(("Received IRP for unknown Device Object")); Status = STATUS_NOT_SUPPORTED; break; } // // Complete the Irp and return. // if (Status != STATUS_NOT_SUPPORTED) { Irp->IoStatus.Status = Status; } else { Status = Irp->IoStatus.Status ; } IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS HalpDispatchPower( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) /*++ Routine Description: This routine handles all IRP_MJ_POWER IRPs for madeup device. Arguments: DeviceObject - Pointer to the device object for which this IRP applies. Irp - Pointer to the IRP_MJ_POWER IRP to dispatch. Return Value: NT status. --*/ { NTSTATUS Status; EXTENSION_TYPE extensionType; PIO_STACK_LOCATION irpSp; HalPrint(("Power IRP for DevObj: %x", DeviceObject)); // // Simply store the appropriate status and complete the request. // extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType; irpSp = IoGetCurrentIrpStackLocation(Irp); // // Simply store the appropriate status and complete the request. // Status = Irp->IoStatus.Status; if ((irpSp->MinorFunction == IRP_MN_QUERY_POWER) || (irpSp->MinorFunction == IRP_MN_SET_POWER)) { Irp->IoStatus.Status = Status = STATUS_SUCCESS; } else if (irpSp->MinorFunction == IRP_MN_WAIT_WAKE) { // // Fail this explicitly as we don't know how to wake the system... // Irp->IoStatus.Status = Status = STATUS_NOT_SUPPORTED; } PoStartNextPowerIrp(Irp); if (extensionType == PdoExtensionType) { IoCompleteRequest( Irp, IO_NO_INCREMENT ); } else { #ifdef APIC_HAL if (irpSp->MinorFunction == IRP_MN_SET_POWER) { if (irpSp->Parameters.Power.Type == SystemPowerState) { switch (irpSp->Parameters.Power.State.SystemState) { case PowerSystemHibernate: HalpBuildResumeStructures(); break; case PowerSystemWorking: HalpFreeResumeStructures(); break; default: break; } } } #endif Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp); } return Status; } NTSTATUS HalpDispatchWmi( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { NTSTATUS Status; EXTENSION_TYPE extensionType; extensionType = ((PFDO_EXTENSION)(DeviceObject->DeviceExtension))->ExtensionType; if (extensionType == FdoExtensionType) { Status = HalpPassIrpFromFdoToPdo(DeviceObject, Irp); } else { Status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return Status; } NTSTATUS HalpQueryDeviceRelations( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE RelationType, OUT PDEVICE_RELATIONS *DeviceRelations ) /*++ Routine Description: This routine builds a DEVICE_RELATIONS structure that tells the PnP manager how many children we have. Arguments: DeviceObject - FDO of PCI_HAL RelationType - we only respond to BusRelations DeviceRelations - pointer to the structure Return Value: status --*/ { PFDO_EXTENSION FdoExtension; PDEVICE_RELATIONS relations = NULL; ULONG count; PDEVICE_OBJECT *Pdo; PDEVICE_OBJECT Pdo2; EXTENSION_TYPE extensionType; PAGED_CODE(); FdoExtension = (PFDO_EXTENSION)DeviceObject->DeviceExtension; extensionType = FdoExtension->ExtensionType; count = FdoExtension->BusCount; switch (RelationType) { case BusRelations: if ((extensionType == PdoExtensionType)||(count == 0)) { // // Don't touch the IRP // return STATUS_NOT_SUPPORTED ; } if (*DeviceRelations != NULL) { count += (*DeviceRelations)->Count; } relations = ExAllocatePoolWithTag( PagedPool, sizeof(DEVICE_RELATIONS) + (count - 1) * sizeof( PDEVICE_OBJECT), HAL_POOL_TAG ); if (relations == NULL) { HalPrint(("HalpQueryDeviceRelations: couldn't allocate pool")); return STATUS_INSUFFICIENT_RESOURCES; } relations->Count = count; Pdo = relations->Objects; count = 0; if (*DeviceRelations != NULL) { for ( count = 0; count < (*DeviceRelations)->Count; count++) { *Pdo = (*DeviceRelations)->Objects[count]; Pdo++; } ExFreePool(*DeviceRelations); } // // Add our PDO's to the list. // Pdo2 = FdoExtension->ChildPdoList; while (Pdo2 != NULL) { *Pdo = Pdo2; ObReferenceObject(Pdo2); Pdo2 = ((PPDO_EXTENSION) Pdo2->DeviceExtension)->Next; Pdo++; ASSERT( count++ < relations->Count ); } *DeviceRelations = relations; return STATUS_SUCCESS; case TargetDeviceRelation: if (extensionType == FdoExtensionType) { // // Don't touch the IRP // return STATUS_NOT_SUPPORTED ; } relations = ExAllocatePoolWithTag( PagedPool, sizeof(DEVICE_RELATIONS), HAL_POOL_TAG ); if (!relations) { return STATUS_INSUFFICIENT_RESOURCES; } relations->Count = 1; relations->Objects[0] = DeviceObject ; ObReferenceObject(relations->Objects[0]); *DeviceRelations = relations; return STATUS_SUCCESS ; default: break; } HalPrint(("We don't support this kind of device relation")); return STATUS_NOT_SUPPORTED ; } NTSTATUS HalpQueryIdPdo( IN PDEVICE_OBJECT DeviceObject, IN BUS_QUERY_ID_TYPE IdType, IN OUT PWSTR *BusQueryId ) /*++ Routine Description: This routine identifies each of the children that were enumerated in HalpQueryDeviceRelations. Arguments: DeviceObject - PDO of the child IdType - the type of ID to be returned. BusQueryId - pointer to the wide string being returned Return Value: status --*/ { PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension; PWSTR idString; PWCHAR sourceString = NULL; ULONG stringLen; UNICODE_STRING String; WCHAR Buffer[16]; NTSTATUS Status; static WCHAR PciHardwareIdString[] = L"PCI_HAL\\PNP0A03"; static WCHAR PciCompatibleString[] = L"*PNP0A03"; static WCHAR IsaHardwareIdString[] = L"ISA_HAL\\PNP0A00"; static WCHAR IsaCompatibleString[] = L"*PNP0A00"; static WCHAR McaHardwareIdString[] = L"ISA_HAL\\PNP0A02"; static WCHAR McaCompatibleString[] = L"*PNP0A02"; PAGED_CODE(); switch (IdType) { case BusQueryDeviceID: case BusQueryHardwareIDs: if (PdoExtension->PdoType == PciDriver) { sourceString = PciHardwareIdString; stringLen = sizeof(PciHardwareIdString); } else if (PdoExtension->PdoType == IsaPnpDriver) { sourceString = IsaHardwareIdString; stringLen = sizeof(IsaHardwareIdString); } else if (PdoExtension->PdoType == McaDriver) { sourceString = McaHardwareIdString; stringLen = sizeof(McaHardwareIdString); } break; case BusQueryCompatibleIDs: if (PdoExtension->PdoType == PciDriver) { sourceString = PciCompatibleString; stringLen = sizeof(PciCompatibleString); } else if (PdoExtension->PdoType == IsaPnpDriver) { sourceString = IsaCompatibleString; stringLen = sizeof(IsaCompatibleString); } else if (PdoExtension->PdoType == McaDriver) { sourceString = McaCompatibleString; stringLen = sizeof(McaCompatibleString); } break; case BusQueryInstanceID: String.Buffer = Buffer; String.MaximumLength = 16 * sizeof(WCHAR); Status = RtlIntegerToUnicodeString( PdoExtension->BusNumber, 10, &String ); // // Note the string length in this case does not include a NULL. // the code below will terminate the string with NULL. // sourceString = Buffer; stringLen = String.Length; break; } if (sourceString) { // // Note that hardware IDs and compatible IDs must be terminated by // 2 NULLs. // idString = ExAllocatePoolWithTag(PagedPool, stringLen + sizeof(UNICODE_NULL), HAL_POOL_TAG); if (!idString) { HalPrint(("HalpQueryIdPdo: couldn't allocate pool\n")); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(idString, sourceString, stringLen); *(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL; *BusQueryId = idString; return STATUS_SUCCESS; } else { return STATUS_NOT_SUPPORTED; } } NTSTATUS HalpQueryIdFdo( IN PDEVICE_OBJECT DeviceObject, IN BUS_QUERY_ID_TYPE IdType, IN OUT PWSTR *BusQueryId ) /*++ Routine Description: This routine identifies each of the children that were enumerated in HalpQueryDeviceRelations. Arguments: DeviceObject - PDO of the child IdType - the type of ID to be returned. BusQueryId - pointer to the wide string being returned Return Value: status --*/ { PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension; PWSTR idString; PWCHAR sourceString = NULL; ULONG stringLen; UNICODE_STRING String; WCHAR Buffer[16]; NTSTATUS Status; PWCHAR widechar; static WCHAR HalInstanceIdString[] = L"0"; PAGED_CODE(); switch (IdType) { case BusQueryDeviceID: case BusQueryHardwareIDs: // // For the UP version of the APIC HAL, we want to detect if there is more // than one processor installed. If so, we want to return the ID of // the MP HAL rather than the UP HAL. This will induce PNP to reconfigure // our devnode and setup the MP HAL for the next boot. // sourceString = HalHardwareIdString; #if defined(NT_UP) && defined(APIC_HAL) if (HalpMpInfoTable.ProcessorCount > 1) { sourceString = MpHalHardwareIdString; } #endif widechar = sourceString; while (*widechar != UNICODE_NULL) { widechar++; } stringLen = (PUCHAR)widechar - ((PUCHAR)sourceString) + 2; break; case BusQueryInstanceID: sourceString = HalInstanceIdString; stringLen = sizeof(HalInstanceIdString); break; default: break; } if (sourceString) { // // Note that hardware IDs and compatible IDs must be terminated by // 2 NULLs. // idString = ExAllocatePoolWithTag(PagedPool, stringLen + sizeof(UNICODE_NULL), HAL_POOL_TAG); if (!idString) { HalPrint(("HalpQueryIdFdo: couldn't allocate pool\n")); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(idString, sourceString, stringLen); *(idString + stringLen / sizeof(WCHAR)) = UNICODE_NULL; *BusQueryId = idString; return STATUS_SUCCESS; } else { return STATUS_NOT_SUPPORTED; } } NTSTATUS HalpQueryCapabilities( IN PDEVICE_OBJECT Pdo, IN PDEVICE_CAPABILITIES Capabilities ) /*++ Routine Description: This routine fills in the DEVICE_CAPABILITIES structure for a device. Arguments: DeviceObject - PDO of the child Capabilities - pointer to the structure to be filled in. Return Value: status --*/ { PPDO_EXTENSION PdoExtension = (PPDO_EXTENSION) Pdo->DeviceExtension; PAGED_CODE(); ASSERT_PDO_EXTENSION( PdoExtension ); ASSERT(Capabilities->Version == 1); if (Capabilities->Version != 1) { return STATUS_NOT_SUPPORTED; } Capabilities->LockSupported = FALSE; Capabilities->EjectSupported = FALSE; Capabilities->Removable = FALSE; Capabilities->DockDevice = FALSE; Capabilities->UniqueID = TRUE; Capabilities->SilentInstall = TRUE; Capabilities->RawDeviceOK = FALSE; Capabilities->Address = PdoExtension->BusNumber; Capabilities->UINumber = PdoExtension->BusNumber; Capabilities->D1Latency = 0; Capabilities->D2Latency = 0; Capabilities->D3Latency = 0; // // Default S->D mapping // Capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0; Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3; Capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3; // // Make it work on NTAPM --- note that we might have to check to see // if the machine supports APM before we do this // Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3; return STATUS_SUCCESS; } NTSTATUS HalpQueryInterface( IN PDEVICE_OBJECT DeviceObject, IN LPCGUID InterfaceType, IN USHORT Version, IN PVOID InterfaceSpecificData, IN ULONG InterfaceBufferSize, IN OUT PINTERFACE Interface, IN OUT PULONG Length ) /*++ Routine Description: This routine fills in the interface structure for a device. Arguments: DeviceObject - PDO of the child InterfaceType - Pointer to the interface type GUID. Version - Supplies the requested interface version. InterfaceSpecificData - This is context that means something based on the interface. InterfaceBufferSize - Supplies the length of the buffer for the interface structure. Interface - Supplies a pointer where the interface informaiton should be returned. Length - This value is updated on return to actual number of bytes modified. Return Value: status --*/ { PPDO_EXTENSION PdoExtension = (PPDO_EXTENSION)DeviceObject->DeviceExtension; CM_RESOURCE_TYPE resource = (CM_RESOURCE_TYPE)InterfaceSpecificData; PAGED_CODE(); ASSERT_PDO_EXTENSION(PdoExtension); if (IsEqualGUID(&GUID_BUS_INTERFACE_STANDARD, InterfaceType)) { PBUS_INTERFACE_STANDARD standard = (PBUS_INTERFACE_STANDARD)Interface; // // ASSERT we know about all of the fields in the structure. // ASSERT(sizeof(BUS_INTERFACE_STANDARD) == FIELD_OFFSET(BUS_INTERFACE_STANDARD, GetBusData) + sizeof(PGET_SET_DEVICE_DATA)); *Length = sizeof(BUS_INTERFACE_STANDARD); if (InterfaceBufferSize < sizeof(BUS_INTERFACE_STANDARD)) { return STATUS_BUFFER_TOO_SMALL; } // // The only version this code knows about is 1. // standard->Size = sizeof(BUS_INTERFACE_STANDARD); standard->Version = HAL_BUS_INTERFACE_STD_VERSION; standard->Context = DeviceObject; standard->InterfaceReference = HalPnpInterfaceReference; standard->InterfaceDereference = HalPnpInterfaceDereference; standard->TranslateBusAddress = HalPnpTranslateBusAddress; standard->GetDmaAdapter = HalPnpGetDmaAdapter; standard->SetBusData = NULL; standard->GetBusData = NULL; } else if ((IsEqualGUID(&GUID_PCI_BUS_INTERFACE_STANDARD, InterfaceType)) && (PdoExtension->PdoType == PciDriver)) { PPCI_BUS_INTERFACE_STANDARD pciStandard = (PPCI_BUS_INTERFACE_STANDARD)Interface; *Length = sizeof(PCI_BUS_INTERFACE_STANDARD); if (InterfaceBufferSize < sizeof(PCI_BUS_INTERFACE_STANDARD)) { return STATUS_BUFFER_TOO_SMALL; } // // Fill in the interface, which is used for reading and // writing PCI configuration space. // pciStandard->Size = sizeof(PCI_BUS_INTERFACE_STANDARD); pciStandard->Version = PCI_BUS_INTERFACE_STANDARD_VERSION; pciStandard->Context = DeviceObject; pciStandard->InterfaceReference = HalPnpInterfaceReference; pciStandard->InterfaceDereference = HalPnpInterfaceDereference; pciStandard->ReadConfig = HaliPciInterfaceReadConfig; pciStandard->WriteConfig = HaliPciInterfaceWriteConfig; pciStandard->PinToLine = NULL; pciStandard->LineToPin = NULL; #if 0 } else if (IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType)) { PTRANSLATOR_INTERFACE translator = (PTRANSLATOR_INTERFACE)Interface; if (InterfaceBufferSize < sizeof(TRANSLATOR_INTERFACE)) { *Length = sizeof(TRANSLATOR_INTERFACE); return STATUS_BUFFER_TOO_SMALL; } switch ((CM_RESOURCE_TYPE)InterfaceSpecificData) { case CmResourceTypeInterrupt: switch(PdoExtension->PdoType) { case PciDriver: translator->Context = (PVOID)PCIBus; break; case IsaPnpDriver: translator->Context = (PVOID)Isa; break; case McaDriver: translator->Context = (PVOID)MicroChannel; break; default: // // Don't know how to handle this. // HalPrint(("HAL: PDO %08x unknown Type 0x%x, failing QueryInterface\n", DeviceObject, PdoExtension->PdoType )); return STATUS_NOT_SUPPORTED; } translator->Version = HAL_IRQ_TRANSLATOR_VERSION; translator->TranslateResources = HalIrqTranslateResourcesRoot; translator->TranslateResourceRequirements = HalIrqTranslateResourceRequirementsRoot; break; // Truth is, halx86 doesn't provide translators for memory or // io resources either. But if it did, it would look like this. case CmResourceTypeMemory: case CmResourceTypePort: translator->Context = DeviceObject; translator->Version = HAL_MEMIO_TRANSLATOR_VERSION; translator->TranslateResources = HalpTransMemIoResource; translator->TranslateResourceRequirements = HalpTransMemIoResourceRequirement; break; default: return STATUS_NOT_SUPPORTED; } // // Common initialization // translator->Size = sizeof(TRANSLATOR_INTERFACE); translator->InterfaceReference = HalPnpInterfaceReference; translator->InterfaceDereference = HalPnpInterfaceDereference; *Length = sizeof(TRANSLATOR_INTERFACE); #endif #ifdef WANT_IRQ_ROUTING } else if ( IsPciIrqRoutingEnabled() && IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType) && resource == CmResourceTypeInterrupt && PdoExtension->PdoType == PciDriver) { // // We want to arbitrate on untranslated resources, so we get rid of Irq // translator provided by Pci iff Irq Routing is enabled. // HalPrint(("Getting rid of Pci Irq translator interface since Pci Irq Routing is enabled!")); RtlZeroMemory((LPGUID)InterfaceType, sizeof(GUID)); return STATUS_NOT_SUPPORTED; #endif } else { // // Unsupport bus interface type. // return STATUS_NOT_SUPPORTED ; } // // Bump the reference count. // InterlockedIncrement(&PdoExtension->InterfaceReferenceCount); return STATUS_SUCCESS; } #ifdef WANT_IRQ_ROUTING NTSTATUS HalpQueryInterfaceFdo( IN PDEVICE_OBJECT DeviceObject, IN LPCGUID InterfaceType, IN USHORT Version, IN PVOID InterfaceSpecificData, IN ULONG InterfaceBufferSize, IN OUT PINTERFACE Interface, IN OUT PULONG Length ) /*++ Routine Description: This routine fills in the interface structure for a device. Arguments: DeviceObject - FDO of the child InterfaceType - Pointer to the interface type GUID. Version - Supplies the requested interface version. InterfaceSpecificData - This is context that means something based on the interface. InterfaceBufferSize - Supplies the length of the buffer for the interface structure. Interface - Supplies a pointer where the interface informaiton should be returned. Length - Supplies the length of the buffer for the interface structure. This value is updated on return to actual number of bytes modified. Return Value: status --*/ { NTSTATUS status = STATUS_NOT_SUPPORTED; CM_RESOURCE_TYPE resource = (CM_RESOURCE_TYPE)InterfaceSpecificData; PAGED_CODE(); if ( resource == CmResourceTypeInterrupt && IsPciIrqRoutingEnabled()) { if (IsEqualGUID(&GUID_ARBITER_INTERFACE_STANDARD, InterfaceType)) { status = HalpInitIrqArbiter(DeviceObject); if (NT_SUCCESS(status)) { status = HalpFillInIrqArbiter( DeviceObject, InterfaceType, Version, InterfaceSpecificData, InterfaceBufferSize, Interface, Length ); } } else if (IsEqualGUID(&GUID_TRANSLATOR_INTERFACE_STANDARD, InterfaceType)) { PTRANSLATOR_INTERFACE translator; *Length = sizeof(TRANSLATOR_INTERFACE); if (InterfaceBufferSize < sizeof(TRANSLATOR_INTERFACE)) { return STATUS_BUFFER_TOO_SMALL; } translator = (PTRANSLATOR_INTERFACE)Interface; // // Fill in the common bits. // RtlZeroMemory(translator, sizeof (TRANSLATOR_INTERFACE)); translator->Size = sizeof(TRANSLATOR_INTERFACE); translator->Version = HAL_IRQ_TRANSLATOR_VERSION; translator->Context = DeviceObject; translator->InterfaceReference = HalTranslatorReference; translator->InterfaceDereference = HalTranslatorDereference; // // Set IRQ translator for PCI interrupts. // translator->TranslateResources = HalIrqTranslateResourcesRoot; translator->TranslateResourceRequirements = HalIrqTranslateResourceRequirementsRoot; status = STATUS_SUCCESS; HalPrint(("Providing Irq translator for FDO %08x since Pci Irq Routing is enabled!", DeviceObject)); } } return (status); } #endif NTSTATUS HalpQueryDeviceText( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_TEXT_TYPE IdType, IN OUT PWSTR *BusQueryId ) /*++ Routine Description: This routine identifies each of the children that were enumerated in HalpQueryDeviceRelations. Arguments: DeviceObject - PDO of the child IdType - the type of ID to be returned. BusQueryId - pointer to the wide string being returned Return Value: status --*/ { PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension; PWSTR idString; PWCHAR sourceString = NULL; ULONG stringLen; NTSTATUS Status; static WCHAR PciDeviceNameText[] = L"Pci Root Bus"; static WCHAR IsaDeviceNameText[] = L"Isa Root Bus"; static WCHAR McaDeviceNameText[] = L"Mca Root Bus"; PAGED_CODE(); if (PdoExtension->PdoType == PciDriver) { sourceString = PciDeviceNameText; stringLen = sizeof(PciDeviceNameText); } else if (PdoExtension->PdoType == IsaPnpDriver) { sourceString = IsaDeviceNameText; stringLen = sizeof(IsaDeviceNameText); } else if (PdoExtension->PdoType == McaDriver) { sourceString = McaDeviceNameText; stringLen = sizeof(McaDeviceNameText); } if (sourceString) { switch (IdType) { case DeviceTextDescription: case DeviceTextLocationInformation: idString = ExAllocatePoolWithTag(PagedPool, stringLen, HAL_POOL_TAG); if (!idString) { HalPrint(("HalpQueryDeviceText: couldn't allocate pool\n")); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(idString, sourceString, stringLen); *BusQueryId = idString; return STATUS_SUCCESS; } } return STATUS_NOT_SUPPORTED; } NTSTATUS HalpQueryResources( IN PDEVICE_OBJECT DeviceObject, IN PCM_RESOURCE_LIST *Resources ) /*++ Routine Description: This routine handles IRP_MN_QUERY_RESOURCE_REQUIREMENTS. Arguments: DeviceObject - PDO of the child Resources - pointer to be filled in with the devices resource list. Return Value: status --*/ { PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension; PCM_RESOURCE_LIST ResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; PSUPPORTED_RANGE Range; ULONG ResourceListSize; ULONG Count = 1; if (PdoExtension->PdoType != PciDriver) { *Resources = NULL; return STATUS_SUCCESS; } // // Determine the number of resourse list needed. Already counted // one for the Bus Number. // for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Count++; } for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Count++; } for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Count++; } // // Convert this resourceListSize into the number of bytes that we // must allocate // ResourceListSize = sizeof(CM_RESOURCE_LIST) + ( (Count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) ); ResourceList = ExAllocatePoolWithTag( PagedPool, ResourceListSize, HAL_POOL_TAG); if (ResourceList == NULL ) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory( ResourceList, ResourceListSize ); // // Initialize the list header. // ResourceList->Count = 1; ResourceList->List[0].InterfaceType = PNPBus; ResourceList->List[0].BusNumber = -1; ResourceList->List[0].PartialResourceList.Version = 1; ResourceList->List[0].PartialResourceList.Revision = 1; ResourceList->List[0].PartialResourceList.Count = Count; Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors; // // Create descriptor for the Bus Number. // Descriptor->Type = CmResourceTypeBusNumber; Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->u.BusNumber.Start = PdoExtension->BusNumber; Descriptor->u.BusNumber.Length = PdoExtension->MaxSubordinateBusNumber - PdoExtension->BusNumber + 1; Descriptor++; for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Descriptor->Type = CmResourceTypePort; Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->Flags = CM_RESOURCE_PORT_IO; Descriptor->u.Port.Length = (ULONG)(Range->Limit - Range->Base) + 1; Descriptor->u.Port.Start.QuadPart = Range->Base; Descriptor++; } for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Descriptor->Type = CmResourceTypeMemory; Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; Descriptor->u.Memory.Length = (ULONG)(Range->Limit - Range->Base) + 1; Descriptor->u.Memory.Start.QuadPart = Range->Base; Descriptor++; } for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Descriptor->Type = CmResourceTypeMemory; Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE; Descriptor->u.Memory.Length = (ULONG)(Range->Limit - Range->Base) + 1; Descriptor->u.Memory.Start.QuadPart = Range->Base; Descriptor++; } *Resources = ResourceList; return STATUS_SUCCESS; } NTSTATUS HalpQueryResourceRequirements( IN PDEVICE_OBJECT DeviceObject, IN PIO_RESOURCE_REQUIREMENTS_LIST *Requirements ) /*++ Routine Description: This routine handles IRP_MN_QUERY_RESOURCE_REQUIREMENTS. Arguments: DeviceObject - PDO of the child Requirements - pointer to be filled in with the devices resource requirements. Return Value: status --*/ { PPDO_EXTENSION PdoExtension = DeviceObject->DeviceExtension; PIO_RESOURCE_REQUIREMENTS_LIST ResourceList; PIO_RESOURCE_DESCRIPTOR Descriptor; PSUPPORTED_RANGE Range; ULONG ResourceListSize; ULONG Count = 0; if (PdoExtension->PdoType != PciDriver) { *Requirements = NULL; return STATUS_SUCCESS; } // // Determine the number of resourse list needed. // for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Count++; } for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Count++; } for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Count++; } // // Convert this resourceListSize into the number of bytes that we // must allocate // ResourceListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + ( (Count - 1) * sizeof(IO_RESOURCE_DESCRIPTOR) ); ResourceList = ExAllocatePoolWithTag( PagedPool, ResourceListSize, HAL_POOL_TAG); if (ResourceList == NULL ) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory( ResourceList, ResourceListSize ); ResourceList->ListSize = ResourceListSize; // // Initialize the list header. // ResourceList->AlternativeLists = 1; ResourceList->InterfaceType = PNPBus; ResourceList->BusNumber = -1; ResourceList->List[0].Version = 1; ResourceList->List[0].Revision = 1; ResourceList->List[0].Count = Count; Descriptor = ResourceList->List[0].Descriptors; for (Range = &PdoExtension->Bus->BusAddresses->IO; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Descriptor->Type = CmResourceTypePort; Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->Flags = CM_RESOURCE_PORT_IO; Descriptor->u.Port.Length = (ULONG) (Range->Limit - Range->Base + 1); Descriptor->u.Port.Alignment = 0x01; Descriptor->u.Port.MinimumAddress.QuadPart = Range->Base; Descriptor->u.Port.MaximumAddress.QuadPart = Range->Limit; Descriptor++; } for (Range = &PdoExtension->Bus->BusAddresses->Memory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Descriptor->Type = CmResourceTypeMemory; Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; Descriptor->u.Memory.Length = (ULONG) (Range->Limit - Range->Base + 1); Descriptor->u.Memory.Alignment = 0x01; Descriptor->u.Memory.MinimumAddress.QuadPart = Range->Base; Descriptor->u.Memory.MaximumAddress.QuadPart = Range->Limit; Descriptor++; } for (Range = &PdoExtension->Bus->BusAddresses->PrefetchMemory; Range != NULL; Range = Range->Next) { // // If the limit is zero then skip this entry. // if (Range->Limit == 0) { continue; } Descriptor->Type = CmResourceTypeMemory; Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE; Descriptor->u.Memory.Length = (ULONG) (Range->Limit - Range->Base + 1); Descriptor->u.Memory.Alignment = 0x01; Descriptor->u.Memory.MinimumAddress.QuadPart = Range->Base; Descriptor->u.Memory.MaximumAddress.QuadPart = Range->Limit; Descriptor++; } *Requirements = ResourceList; return STATUS_SUCCESS; } NTSTATUS HalpRemoveAssignedResources ( PBUS_HANDLER Bus ) /* Routine Description: Reads the rgzResourceMap in the registry and builds a canonical list of all in use resources ranges by resource type. Arguments: */ { HANDLE ClassKeyHandle, DriverKeyHandle; HANDLE ResourceMap; ULONG ClassKeyIndex, DriverKeyIndex, DriverValueIndex; PCM_RESOURCE_LIST CmResList; PCM_FULL_RESOURCE_DESCRIPTOR CmFResDesc; PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc; UNICODE_STRING KeyName; ULONG BufferSize; union { PVOID Buffer; PKEY_BASIC_INFORMATION KeyBInf; PKEY_FULL_INFORMATION KeyFInf; PKEY_VALUE_FULL_INFORMATION VKeyFInf; } U; PUCHAR LastAddr; ULONG Temp, Length, i, j; ULONG TranslatedStrLen; ULONG BusTranslatedStrLen; NTSTATUS Status; LONGLONG li; PAGED_CODE(); // // Removed page zero. // HalpRemoveRange( &Bus->BusAddresses->Memory, 0i64, (LONGLONG) (PAGE_SIZE - 1) ); // // Start out with one page of buffer. // BufferSize = PAGE_SIZE; U.Buffer = ExAllocatePoolWithTag( PagedPool, BufferSize, HAL_POOL_TAG); if (U.Buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } for (TranslatedStrLen=0; rgzTranslated[TranslatedStrLen]; TranslatedStrLen++) ; for (BusTranslatedStrLen=0; rgzBusTranslated[BusTranslatedStrLen]; BusTranslatedStrLen++) ; TranslatedStrLen *= sizeof (WCHAR); BusTranslatedStrLen *= sizeof (WCHAR); RtlInitUnicodeString( &KeyName, rgzResourceMap ); Status = HalpOpenRegistryKey( &ResourceMap, NULL, &KeyName, KEY_READ, FALSE ); if (!NT_SUCCESS( Status )) { HalPrint(("HalRemoveSystemResourcesFromPci: Failed to open resource map key Status = %lx\n", Status )); ExFreePool( U.Buffer ); return Status; } // // Walk resource map and collect any inuse resources // ClassKeyIndex = 0; ClassKeyHandle = INVALID_HANDLE; DriverKeyHandle = INVALID_HANDLE; Status = STATUS_SUCCESS; while (NT_SUCCESS(Status)) { // // Get the class information // Status = ZwEnumerateKey( ResourceMap, ClassKeyIndex++, KeyBasicInformation, U.KeyBInf, BufferSize, &Temp ); if (!NT_SUCCESS( Status )) { break; } // // Create a UNICODE_STRING using the counted string passed back to // us in the information structure, and open the class key. // KeyName.Buffer = (PWSTR) U.KeyBInf->Name; KeyName.Length = (USHORT) U.KeyBInf->NameLength; KeyName.MaximumLength = (USHORT) U.KeyBInf->NameLength; Status = HalpOpenRegistryKey( &ClassKeyHandle, ResourceMap, &KeyName, KEY_READ, FALSE ); if (!NT_SUCCESS( Status )) { break; } DriverKeyIndex = 0; while (NT_SUCCESS (Status)) { // // Get the class information // Status = ZwEnumerateKey( ClassKeyHandle, DriverKeyIndex++, KeyBasicInformation, U.KeyBInf, BufferSize, &Temp ); if (!NT_SUCCESS( Status )) { break; } // // Create a UNICODE_STRING using the counted string passed back to // us in the information structure, and open the class key. // // This is read from the key we created, and the name // was NULL terminated. // KeyName.Buffer = (PWSTR) U.KeyBInf->Name; KeyName.Length = (USHORT) U.KeyBInf->NameLength; KeyName.MaximumLength = (USHORT) U.KeyBInf->NameLength; Status = HalpOpenRegistryKey( &DriverKeyHandle, ClassKeyHandle, &KeyName, KEY_READ, FALSE); if (!NT_SUCCESS( Status )) { break; } // // Get full information for that key so we can get the // information about the data stored in the key. // Status = ZwQueryKey( DriverKeyHandle, KeyFullInformation, U.KeyFInf, BufferSize, &Temp ); if (!NT_SUCCESS( Status )) { break; } Length = sizeof( KEY_VALUE_FULL_INFORMATION ) + U.KeyFInf->MaxValueNameLen + U.KeyFInf->MaxValueDataLen + sizeof(UNICODE_NULL); if (Length > BufferSize) { PVOID TempBuffer; // // Get a larger buffer // TempBuffer = ExAllocatePoolWithTag( PagedPool, Length, HAL_POOL_TAG); if (TempBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } ExFreePool (U.Buffer); U.Buffer = TempBuffer; BufferSize = Length; } DriverValueIndex = 0; for (; ;) { Status = ZwEnumerateValueKey( DriverKeyHandle, DriverValueIndex++, KeyValueFullInformation, U.VKeyFInf, BufferSize, &Temp ); if (!NT_SUCCESS( Status )) { break; } // // If this is not a translated resource list, skip it. // i = U.VKeyFInf->NameLength; if (i < TranslatedStrLen || RtlCompareMemory ( ((PUCHAR) U.VKeyFInf->Name) + i - TranslatedStrLen, rgzTranslated, TranslatedStrLen ) != TranslatedStrLen ) { // does not end in rgzTranslated continue; } // // If this is a bus translated resource list, ???? // if (i >= BusTranslatedStrLen && RtlCompareMemory ( ((PUCHAR) U.VKeyFInf->Name) + i - BusTranslatedStrLen, rgzBusTranslated, BusTranslatedStrLen ) == BusTranslatedStrLen ) { // ends in rgzBusTranslated continue; } // // Run the CmResourceList and save each InUse resource // CmResList = (PCM_RESOURCE_LIST) ( (PUCHAR) U.VKeyFInf + U.VKeyFInf->DataOffset); LastAddr = (PUCHAR) CmResList + U.VKeyFInf->DataLength; CmFResDesc = &CmResList->List[0]; for (i=0; i < CmResList->Count && NT_SUCCESS(Status) ; i++) { for (j=0; j < CmFResDesc->PartialResourceList.Count && NT_SUCCESS(Status); j++) { CmDesc = &CmFResDesc->PartialResourceList.PartialDescriptors[j]; if ((PUCHAR) (CmDesc+1) > LastAddr) { if (i) { HalPrint(("IopAssignResourcesPhase2: a. CmResourceList in regitry too short\n")); } break; } if ((PUCHAR) (CmDesc+1) > LastAddr) { i = CmResList->Count; HalPrint(("IopAssignResourcesPhase2: b. CmResourceList in regitry too short\n")); break; } switch (CmDesc->Type) { case CmResourceTypePort: HalpRemoveRange( &Bus->BusAddresses->IO, CmDesc->u.Generic.Start.QuadPart, CmDesc->u.Generic.Start.QuadPart + CmDesc->u.Generic.Length - 1 ); break; case CmResourceTypeMemory: // // The HAL's notion of prefetchable may not be // consistent. So just remove any memory resource // from both the prefetchable and non-prefetchable // lists. // HalpRemoveRange( &Bus->BusAddresses->PrefetchMemory, CmDesc->u.Generic.Start.QuadPart, CmDesc->u.Generic.Start.QuadPart + CmDesc->u.Generic.Length - 1 ); HalpRemoveRange( &Bus->BusAddresses->Memory, CmDesc->u.Generic.Start.QuadPart, CmDesc->u.Generic.Start.QuadPart + CmDesc->u.Generic.Length - 1 ); break; default: break; } } // // Start at the end of the last CmDesc // since the PCM_PARTIAL_RESOURCE_DESCRIPTOR array // is variable size we can't just use the index. // (PCM_PARTIAL_RESOURCE_DESCRIPTOR) CmFResDesc = CmDesc+1; } } // next DriverValueIndex if (DriverKeyHandle != INVALID_HANDLE) { ZwClose (DriverKeyHandle); DriverKeyHandle = INVALID_HANDLE; } if (Status == STATUS_NO_MORE_ENTRIES) { Status = STATUS_SUCCESS; } if (!NT_SUCCESS(Status)) { break; } } // next DriverKeyIndex if (ClassKeyHandle != INVALID_HANDLE) { ZwClose (ClassKeyHandle); ClassKeyHandle = INVALID_HANDLE; } if (Status == STATUS_NO_MORE_ENTRIES) { Status = STATUS_SUCCESS; } } // next ClassKeyIndex if (Status == STATUS_NO_MORE_ENTRIES) { Status = STATUS_SUCCESS; } ZwClose( ResourceMap ); ExFreePool (U.Buffer); HalpConsolidateRanges (Bus->BusAddresses); return Status; } VOID HalpMarkNonAcpiHal( VOID ) /*++ Routine Description: Arguments: None. Return Value: None. --*/ { ULONG tmpValue; UNICODE_STRING unicodeString; HANDLE hCurrentControlSet, handle; NTSTATUS status; PAGED_CODE(); // // Open/create System\CurrentControlSet key. // RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); status = HalpOpenRegistryKey ( &hCurrentControlSet, NULL, &unicodeString, KEY_ALL_ACCESS, FALSE ); if (!NT_SUCCESS(status)) { return; } // // Open HKLM\System\CurrentControlSet\Control\Pnp // RtlInitUnicodeString(&unicodeString, L"Control\\Pnp"); status = HalpOpenRegistryKey ( &handle, hCurrentControlSet, &unicodeString, KEY_ALL_ACCESS, TRUE ); ZwClose(hCurrentControlSet); if (!NT_SUCCESS(status)) { return; } RtlInitUnicodeString(&unicodeString, L"DisableFirmwareMapper"); tmpValue = 0; ZwSetValueKey(handle, &unicodeString, 0, REG_DWORD, &tmpValue, sizeof(tmpValue) ); ZwClose(handle); } VOID HalpMarkChipsetDecode( BOOLEAN FullDecodeChipset ) /*++ Routine Description: Arguments: FullDecodeChipset - TRUE if NTOSKRNL should consider all fixed I/O descriptors for PNPBIOS devices as 16bit. FALSE if they should be taken at their word. Return Value: None. --*/ { ULONG tmpValue; UNICODE_STRING unicodeString; HANDLE hCurrentControlSet, handle; NTSTATUS status; PAGED_CODE(); // // Open/create System\CurrentControlSet key. // RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); status = HalpOpenRegistryKey ( &hCurrentControlSet, NULL, &unicodeString, KEY_ALL_ACCESS, FALSE ); if (!NT_SUCCESS(status)) { return; } // // Open HKLM\System\CurrentControlSet\Control\Biosinfo\PNPBios // RtlInitUnicodeString(&unicodeString, L"Control\\Biosinfo\\PNPBios"); status = HalpOpenRegistryKey ( &handle, hCurrentControlSet, &unicodeString, KEY_ALL_ACCESS, TRUE ); ZwClose(hCurrentControlSet); if (!NT_SUCCESS(status)) { return; } RtlInitUnicodeString(&unicodeString, L"FullDecodeChipsetOverride"); tmpValue = (ULONG) FullDecodeChipset; ZwSetValueKey(handle, &unicodeString, 0, REG_DWORD, &tmpValue, sizeof(tmpValue) ); ZwClose(handle); } NTSTATUS HalpOpenRegistryKey( OUT PHANDLE Handle, IN HANDLE BaseHandle OPTIONAL, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Create ) /*++ Routine Description: Opens or creates a VOLATILE registry key using the name passed in based at the BaseHandle node. Arguments: Handle - Pointer to the handle which will contain the registry key that was opened. BaseHandle - Handle to the base path from which the key must be opened. KeyName - Name of the Key that must be opened/created. DesiredAccess - Specifies the desired access that the caller needs to the key. Create - Determines if the key is to be created if it does not exist. Return Value: The function value is the final status of the operation. --*/ { OBJECT_ATTRIBUTES objectAttributes; ULONG disposition; PAGED_CODE(); // // Initialize the object for the key. // InitializeObjectAttributes( &objectAttributes, KeyName, OBJ_CASE_INSENSITIVE, BaseHandle, (PSECURITY_DESCRIPTOR) NULL ); // // Create the key or open it, as appropriate based on the caller's // wishes. // if (Create) { return ZwCreateKey( Handle, DesiredAccess, &objectAttributes, 0, (PUNICODE_STRING) NULL, REG_OPTION_VOLATILE, &disposition ); } else { return ZwOpenKey( Handle, DesiredAccess, &objectAttributes ); } } VOID HalPnpInterfaceReference( PVOID Context ) /*++ Routine Description: This function increments the reference count on the interface context. Arguments: Context - Supplies a pointer to the interface context. This is actually the PDO for the root bus. Return Value: None --*/ { PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension; PAGED_CODE(); ASSERT_PDO_EXTENSION( PdoExtension ); InterlockedIncrement( &PdoExtension->InterfaceReferenceCount ); } VOID HalPnpInterfaceDereference( PVOID Context ) /*++ Routine Description: This function decrements the reference count on the interface context. Arguments: Context - Supplies a pointer to the interface context. This is actually the PDO for the root bus. Return Value: None --*/ { PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension; LONG Result; PAGED_CODE(); ASSERT_PDO_EXTENSION( PdoExtension ); Result = InterlockedDecrement( &PdoExtension->InterfaceReferenceCount ); ASSERT( Result >= 0 ); } BOOLEAN HalPnpTranslateBusAddress( IN PVOID Context, IN PHYSICAL_ADDRESS BusAddress, IN ULONG Length, IN OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress ) /*++ Routine Description: This function is used to translate bus addresses from legacy drivers. Arguments: Context - Supplies a pointer to the interface context. This is actually the PDO for the root bus. BusAddress - Supplies the orginal address to be translated. Length - Supplies the length of the range to be translated. AddressSpace - Points to the location of of the address space type such as memory or I/O port. This value is updated by the translation. TranslatedAddress - Returns the translated address. Return Value: Returns a boolean indicating if the operations was a success. --*/ { PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension; PBUS_HANDLER Bus; PAGED_CODE(); ASSERT_PDO_EXTENSION( PdoExtension ); Bus = PdoExtension->Bus; return Bus->TranslateBusAddress( Bus, Bus, BusAddress, AddressSpace, TranslatedAddress ); } ULONG HalPnpReadConfig( IN PVOID Context, IN ULONG Slot, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*++ Routine Description: This function reads the PCI configuration space. Arguments: Context - Supplies a pointer to the interface context. This is actually the PDO for the root bus. Slot - Indicates the slot to be read or writen. Buffer - Supplies a pointer to where the data should be placed. Offset - Indicates the offset into the data where the reading should begin. Length - Indicates the count of bytes which should be read. Return Value: Returns the number of bytes read. --*/ { PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension; PBUS_HANDLER Bus; PAGED_CODE(); ASSERT_PDO_EXTENSION( PdoExtension ); Bus = PdoExtension->Bus; return Bus->GetBusData( Bus, Bus, Slot, Buffer, Offset, Length ); } ULONG HalPnpWriteConfig( IN PVOID Context, IN ULONG Slot, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*++ Routine Description: This function writes the PCI configuration space. Arguments: Context - Supplies a pointer to the interface context. This is actually the PDO for the root bus. Slot - Indicates the slot to be read or writen. Buffer - Supplies a pointer to where the data to be written is. Offset - Indicates the offset into the data where the writing should begin. Length - Indicates the count of bytes which should be written. Return Value: Returns the number of bytes read. --*/ { PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension; PBUS_HANDLER Bus; PAGED_CODE(); ASSERT_PDO_EXTENSION( PdoExtension ); Bus = PdoExtension->Bus; return Bus->SetBusData( Bus, Bus, Slot, Buffer, Offset, Length ); } PDMA_ADAPTER HalPnpGetDmaAdapter( IN PVOID Context, IN struct _DEVICE_DESCRIPTION *DeviceDescriptor, OUT PULONG NumberOfMapRegisters ) /*++ Routine Description: This function writes the PCI configuration space. Arguments: Context - Supplies a pointer to the interface context. This is actually the PDO for the root bus. DeviceDescriptor - Supplies the device descriptor used to allocate the dma adapter object. NubmerOfMapRegisters - Returns the maximum number of map registers a device can allocate at one time. Return Value: Returns a DMA adapter or NULL. --*/ { PPDO_EXTENSION PdoExtension = ((PDEVICE_OBJECT) Context)->DeviceExtension; PBUS_HANDLER Bus; PAGED_CODE(); ASSERT_PDO_EXTENSION( PdoExtension ); Bus = PdoExtension->Bus; // // Fill in the bus number. // DeviceDescriptor->BusNumber = Bus->BusNumber; return (PDMA_ADAPTER) HalGetAdapter( DeviceDescriptor, NumberOfMapRegisters ); } NTSTATUS HalpGetPciInterfaces( IN PDEVICE_OBJECT PciPdo ) /*++ Routine Description: This function queries the PCI driver for interfaces used in interrupt translation and arbitration. Arguments: PciPdo - PDO of a PCI bus Return Value: --*/ { NTSTATUS status; PDEVICE_OBJECT topDeviceInStack; KEVENT irpCompleted; PIRP irp; IO_STATUS_BLOCK statusBlock; PIO_STACK_LOCATION irpStack; PAGED_CODE(); KeInitializeEvent(&irpCompleted, SynchronizationEvent, FALSE); // // Send an IRP to the PCI driver to get the Interrupt Routing Interface. // topDeviceInStack = IoGetAttachedDeviceReference(PciPdo); irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, topDeviceInStack, NULL, // Buffer 0, // Length 0, // StartingOffset &irpCompleted, &statusBlock); if (!irp) { return STATUS_UNSUCCESSFUL; } irp->IoStatus.Status = STATUS_NOT_SUPPORTED; irp->IoStatus.Information = 0; irpStack = IoGetNextIrpStackLocation(irp); // // Set the function codes and parameters. // irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE; irpStack->Parameters.QueryInterface.InterfaceType = &GUID_INT_ROUTE_INTERFACE_STANDARD; irpStack->Parameters.QueryInterface.Size = sizeof(INT_ROUTE_INTERFACE_STANDARD); irpStack->Parameters.QueryInterface.Version = 1; irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) &PciIrqRoutingInterface; irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL; // // Call the driver and wait for completion // status = IoCallDriver(topDeviceInStack, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&irpCompleted, Executive, KernelMode, FALSE, NULL); status = statusBlock.Status; } return status; }