396 lines
10 KiB
C
396 lines
10 KiB
C
/*++
|
||
|
||
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;
|
||
|
||
PPCI_INTERFACE PciInterfaces[] = {
|
||
&ArbiterInterfaceBusNumber,
|
||
&ArbiterInterfaceMemory,
|
||
&ArbiterInterfaceIo,
|
||
&BusHandlerInterface,
|
||
&PciRoutingInterface,
|
||
&PciCardbusPrivateInterface,
|
||
&PciLegacyDeviceDetectionInterface,
|
||
&PciPmeInterface,
|
||
&PciDevicePresentInterface,
|
||
&PciNativeIdeInterface,
|
||
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;
|
||
ULONG index;
|
||
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 = ((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;
|
||
}
|