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.
398 lines
10 KiB
398 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1997-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
interface.c
|
|
|
|
Abstract:
|
|
|
|
IRP_MN_QUERY_INTERFACE lives here.
|
|
|
|
Author:
|
|
|
|
Peter Johnston (peterj) 31-Mar-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pcip.h"
|
|
|
|
|
|
NTSTATUS
|
|
PciGetBusStandardInterface(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
OUT PBUS_INTERFACE_STANDARD BusInterface
|
|
);
|
|
|
|
extern PCI_INTERFACE ArbiterInterfaceBusNumber;
|
|
extern PCI_INTERFACE ArbiterInterfaceMemory;
|
|
extern PCI_INTERFACE ArbiterInterfaceIo;
|
|
extern PCI_INTERFACE TranslatorInterfaceInterrupt;
|
|
extern PCI_INTERFACE TranslatorInterfaceMemory;
|
|
extern PCI_INTERFACE TranslatorInterfaceIo;
|
|
extern PCI_INTERFACE BusHandlerInterface;
|
|
extern PCI_INTERFACE PciRoutingInterface;
|
|
extern PCI_INTERFACE PciCardbusPrivateInterface;
|
|
extern PCI_INTERFACE PciLegacyDeviceDetectionInterface;
|
|
extern PCI_INTERFACE PciPmeInterface;
|
|
extern PCI_INTERFACE PciDevicePresentInterface;
|
|
extern PCI_INTERFACE PciNativeIdeInterface;
|
|
extern PCI_INTERFACE PciLocationInterface;
|
|
extern PCI_INTERFACE AgpTargetInterface;
|
|
|
|
PPCI_INTERFACE PciInterfaces[] = {
|
|
&ArbiterInterfaceBusNumber,
|
|
&ArbiterInterfaceMemory,
|
|
&ArbiterInterfaceIo,
|
|
&BusHandlerInterface,
|
|
&PciRoutingInterface,
|
|
&PciCardbusPrivateInterface,
|
|
&PciLegacyDeviceDetectionInterface,
|
|
&PciPmeInterface,
|
|
&PciDevicePresentInterface,
|
|
&PciNativeIdeInterface,
|
|
&PciLocationInterface,
|
|
&AgpTargetInterface,
|
|
NULL
|
|
};
|
|
|
|
//
|
|
// These are the interfaces we supply only if nobody underneath
|
|
// us (the HAL) does.
|
|
//
|
|
PPCI_INTERFACE PciInterfacesLastResort[] = {
|
|
&TranslatorInterfaceInterrupt,
|
|
NULL
|
|
};
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, PciQueryInterface)
|
|
#pragma alloc_text(PAGE, PciGetBusStandardInterface)
|
|
#endif
|
|
|
|
NTSTATUS
|
|
PciGetBusStandardInterface(
|
|
IN PDEVICE_OBJECT Pdo,
|
|
OUT PBUS_INTERFACE_STANDARD BusInterface
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the bus iterface standard information from the PDO.
|
|
|
|
Arguments:
|
|
|
|
Pdo - Physical device object to query for this information.
|
|
|
|
BusInterface - Supplies a pointer for the retrived information.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
KEVENT event;
|
|
NTSTATUS status;
|
|
PIRP irp;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
PIO_STACK_LOCATION irpStack;
|
|
|
|
PciDebugPrint(
|
|
PciDbgObnoxious,
|
|
"PCI - PciGetBusStandardInterface entered.\n"
|
|
);
|
|
|
|
KeInitializeEvent( &event, NotificationEvent, FALSE );
|
|
|
|
irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
|
|
Pdo,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&event,
|
|
&ioStatusBlock );
|
|
|
|
if (irp == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
irpStack = IoGetNextIrpStackLocation( irp );
|
|
irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|
irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;
|
|
irpStack->Parameters.QueryInterface.Size = sizeof( BUS_INTERFACE_STANDARD );
|
|
irpStack->Parameters.QueryInterface.Version = 1;
|
|
irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) BusInterface;
|
|
irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
|
|
|
//
|
|
// Initialize the status to error in case the ACPI driver decides not to
|
|
// set it correctly.
|
|
//
|
|
|
|
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
|
status = IoCallDriver( Pdo, irp );
|
|
|
|
if (!NT_SUCCESS( status)) {
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciGetBusStandardInterface IoCallDriver returned %08x.\n",
|
|
status
|
|
);
|
|
|
|
return status;
|
|
}
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
|
|
}
|
|
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciGetBusStandardInterface returning status %08x.\n",
|
|
ioStatusBlock.Status
|
|
);
|
|
|
|
return ioStatusBlock.Status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
PciQueryInterface(
|
|
IN PVOID DeviceExtension,
|
|
IN PGUID InterfaceType,
|
|
IN USHORT Size,
|
|
IN USHORT Version,
|
|
IN PVOID InterfaceSpecificData,
|
|
IN OUT PINTERFACE InterfaceReturn,
|
|
IN BOOLEAN LastChance
|
|
)
|
|
{
|
|
PPCI_INTERFACE *interfaceEntry;
|
|
PPCI_INTERFACE interface;
|
|
PPCI_INTERFACE *interfaceTable;
|
|
BOOLEAN isPdo;
|
|
NTSTATUS status;
|
|
|
|
#if DBG
|
|
|
|
UNICODE_STRING guidString;
|
|
|
|
status = RtlStringFromGUID(InterfaceType, &guidString);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciQueryInterface TYPE = %wZ\n",
|
|
&guidString
|
|
);
|
|
RtlFreeUnicodeString(&guidString);
|
|
|
|
PciDebugPrint(
|
|
PciDbgObnoxious,
|
|
" Size = %d, Version = %d, InterfaceData = %x, LastChance = %s\n",
|
|
Size,
|
|
Version,
|
|
InterfaceSpecificData,
|
|
LastChance ? "TRUE" : "FALSE"
|
|
);
|
|
}
|
|
|
|
#endif
|
|
|
|
isPdo = (BOOLEAN)(((PPCI_PDO_EXTENSION)DeviceExtension)->ExtensionType
|
|
== PciPdoExtensionType);
|
|
|
|
//
|
|
// Try to locate the requested interface in the PCI driver's set
|
|
// of exported interfaces.
|
|
//
|
|
// Note - we do not allow last chance interfaces (ie mock translators) for
|
|
// machines where we assign bus numbers
|
|
//
|
|
if (LastChance) {
|
|
|
|
interfaceTable = PciInterfacesLastResort;
|
|
} else {
|
|
interfaceTable = PciInterfaces;
|
|
}
|
|
|
|
for (interfaceEntry = interfaceTable; *interfaceEntry; interfaceEntry++) {
|
|
|
|
interface = *interfaceEntry;
|
|
|
|
#if 0
|
|
status = RtlStringFromGUID(interface->InterfaceType, &guidString);
|
|
if (NT_SUCCESS(status)) {
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciQueryInterface looking at guid = %wZ\n",
|
|
&guidString
|
|
);
|
|
RtlFreeUnicodeString(&guidString);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Check if this interface is allowed to be used from this
|
|
// device object type.
|
|
//
|
|
|
|
if (isPdo) {
|
|
|
|
if ((interface->Flags & PCIIF_PDO) == 0) {
|
|
|
|
//
|
|
// This interface cannot be used from a PDO.
|
|
//
|
|
#if DBG
|
|
status = RtlStringFromGUID(interface->InterfaceType, &guidString);
|
|
if (NT_SUCCESS(status)) {
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciQueryInterface: guid = %wZ only for PDOs\n",
|
|
&guidString
|
|
);
|
|
RtlFreeUnicodeString(&guidString);
|
|
}
|
|
#endif
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Allowable from FDO?
|
|
//
|
|
|
|
if ((interface->Flags & PCIIF_FDO) == 0) {
|
|
|
|
//
|
|
// No.
|
|
//
|
|
#if DBG
|
|
status = RtlStringFromGUID(interface->InterfaceType, &guidString);
|
|
if (NT_SUCCESS(status)) {
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciQueryInterface: guid = %wZ only for FDOs\n",
|
|
&guidString
|
|
);
|
|
RtlFreeUnicodeString(&guidString);
|
|
}
|
|
|
|
#endif
|
|
continue;
|
|
|
|
}
|
|
//
|
|
// Allowable only at root?
|
|
//
|
|
if (interface->Flags & PCIIF_ROOT) {
|
|
|
|
PPCI_FDO_EXTENSION FdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension;
|
|
|
|
if (!PCI_IS_ROOT_FDO(FdoExtension)) {
|
|
|
|
#if DBG
|
|
status = RtlStringFromGUID(interface->InterfaceType, &guidString);
|
|
if (NT_SUCCESS(status)) {
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciQueryInterface: guid = %wZ only for ROOT\n",
|
|
&guidString
|
|
);
|
|
RtlFreeUnicodeString(&guidString);
|
|
}
|
|
#endif
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if DBG
|
|
status = RtlStringFromGUID(interface->InterfaceType, &guidString);
|
|
if (NT_SUCCESS(status)) {
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciQueryInterface looking at guid = %wZ\n",
|
|
&guidString
|
|
);
|
|
RtlFreeUnicodeString(&guidString);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Check for the appropriate GUID then verify version numbers
|
|
// and size.
|
|
//
|
|
|
|
if ((PciCompareGuid(InterfaceType, interface->InterfaceType)) &&
|
|
(Version >= interface->MinVersion) &&
|
|
(Version <= interface->MaxVersion) &&
|
|
(Size >= interface->MinSize) ) {
|
|
|
|
//
|
|
// We have a possible hit. Check to see if the interface
|
|
// itself agrees.
|
|
//
|
|
status = interface->Constructor(
|
|
DeviceExtension,
|
|
interface,
|
|
InterfaceSpecificData,
|
|
Version,
|
|
Size,
|
|
InterfaceReturn
|
|
);
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// We found and allocated an interface, reference it
|
|
// and get out of the loop.
|
|
//
|
|
|
|
InterfaceReturn->InterfaceReference(InterfaceReturn->Context);
|
|
|
|
PciDebugPrint(
|
|
PciDbgObnoxious,
|
|
"PCI - PciQueryInterface returning SUCCESS\n"
|
|
);
|
|
return status;
|
|
#if DBG
|
|
} else {
|
|
|
|
PciDebugPrint(
|
|
PciDbgVerbose,
|
|
"PCI - PciQueryInterface - Contructor %08lx = %08lx\n",
|
|
interface->Constructor,
|
|
status
|
|
);
|
|
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Failed to find the requested interface.
|
|
//
|
|
PciDebugPrint(
|
|
PciDbgObnoxious,
|
|
"PCI - PciQueryInterface FAILED TO FIND INTERFACE\n"
|
|
);
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|