Implement Root Bus FDO AddDevice codes, get boot config, connect to HAL or ACPI config handlers (PciQueryForPciBusInterface, PciGetConfigHandlers), read BUS FDO hack flag, get _HPP HotPlug PCI ACPI data and initialize arbiter support.

PciGetHotPlugParameters work but no PCI HotPlug support on my machines, so cannot test ACPI data, that part stub now
Add PciFdoDispatchTable, PciFdoDispatchPnpTable, PciFdoDispatchPowerTable but all stub to PciIrpNotSupported however set correct IRP Dispatch Style for the IRPS
Arbiter support in PciInitializeARbiters done, but PciInterfaces array is NULL (stub) at moment
Add PCI_SIGNATURE, PCI_STATE, PCI_DISAPTCH_STYLE type, add PciInitializeState to begin the state support
Add structure for PCI_FDO_EXTENSION, PCI_SECONDARY_EXTENSION, PCI_INTERFACE, PCI_ARBITER_INSTANCE, PCI_DISPATCH_TABLE
PCI utility functions added: PciFindParentPciFdoExtension, PciInsertEntryAtTail, PciInsertEntryAtHead, PcipLinkSecondaryExtension, PciGetDeviceProperty, PciSendIoctl
Need sir_richard to add arbiter.h header to define ARBITER_INSTANCE for finish support
This 1000 more codes done now~

svn path=/trunk/; revision=47898
This commit is contained in:
evb 2010-06-28 17:30:35 +00:00
parent ce6c5dd121
commit 6d5d099e85
8 changed files with 1104 additions and 5 deletions

View file

@ -14,6 +14,111 @@
/* GLOBALS ********************************************************************/
PCHAR PciArbiterNames[] =
{
"I/O Port",
"Memory",
"Interrupt",
"Bus Number"
};
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
PciArbiterDestructor(IN PPCI_ARBITER_INSTANCE Arbiter)
{
/* This function is not yet implemented */
UNIMPLEMENTED;
while (TRUE);
}
NTSTATUS
NTAPI
PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
{
PPCI_INTERFACE CurrentInterface, *Interfaces;
PPCI_ARBITER_INSTANCE ArbiterInterface;
NTSTATUS Status;
PCI_SIGNATURE ArbiterType;
ASSERT_FDO(FdoExtension);
/* Loop all the arbiters */
for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++)
{
/* Check if this is the extension for the Root PCI Bus */
if (!PCI_IS_ROOT_FDO(FdoExtension))
{
#if 0 // at next sync when PDO add
/* Get the PDO extension */
PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension;
ASSERT_PDO(PdoExtension);
/* Skip this bus if it does subtractive decode */
if (PdoExtension->Substractive)
{
DPRINT1("PCI Not creating arbiters for subtractive bus %d\n",
PdoExtension->Substractive);
continue;
}
#endif
}
/* Query all the registered arbiter interfaces */
Interfaces = PciInterfaces;
while (*Interfaces)
{
/* Find the one that matches the arbiter currently being setup */
CurrentInterface = *Interfaces;
if (CurrentInterface->Signature == ArbiterType) break;
Interfaces++;
}
/* Check if the required arbiter was not found in the list */
if (!*Interfaces)
{
/* Skip this arbiter and try the next one */
DPRINT1("PCI - FDO ext 0x%08x no %s arbiter.\n",
FdoExtension,
PciArbiterNames[ArbiterType - PciArb_Io]);
continue;
}
/* An arbiter was found, allocate an instance for it */
Status = STATUS_INSUFFICIENT_RESOURCES;
ArbiterInterface = ExAllocatePoolWithTag(PagedPool,
sizeof(PCI_ARBITER_INSTANCE),
PCI_POOL_TAG);
if (!ArbiterInterface) break;
/* Setup the instance */
ArbiterInterface->BusFdoExtension = FdoExtension;
ArbiterInterface->Interface = CurrentInterface;
swprintf(ArbiterInterface->InstanceName,
L"PCI %S (b=%02x)",
PciArbiterNames[ArbiterType - PciArb_Io],
FdoExtension->BaseBus);
/* Call the interface initializer for it */
Status = CurrentInterface->Initializer(ArbiterInterface);
if (!NT_SUCCESS(Status)) break;
/* Link it with this FDO */
PcipLinkSecondaryExtension(&FdoExtension->SecondaryExtension,
&FdoExtension->SecondaryExtLock,
&ArbiterInterface->Header,
ArbiterType,
PciArbiterDestructor);
/* This arbiter is now initialized, move to the next one */
DPRINT1("PCI - FDO ext 0x%08x %S arbiter initialized (context 0x%08x).\n",
FdoExtension,
"ARBITER HEADER MISSING", //ArbiterInterface->CommonInstance.Name,
ArbiterInterface);
Status = STATUS_SUCCESS;
}
/* Return to caller */
return Status;
}
/* EOF */

View file

@ -27,4 +27,16 @@ PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject,
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PciIrpNotSupported(IN PIRP Irp,
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_FDO_EXTENSION DeviceExtension)
{
/* Not supported */
DPRINT1("WARNING: PCI received unsupported IRP!\n");
DbgBreakPoint();
return STATUS_NOT_SUPPORTED;
}
/* EOF */

View file

@ -14,17 +14,306 @@
/* GLOBALS ********************************************************************/
SINGLE_LIST_ENTRY PciFdoExtensionListHead;
BOOLEAN PciBreakOnDefault;
PCI_MN_DISPATCH_TABLE PciFdoDispatchPowerTable[] =
{
{IRP_DISPATCH, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported}
};
PCI_MN_DISPATCH_TABLE PciFdoDispatchPnpTable[] =
{
{IRP_UPWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DISPATCH, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DISPATCH, PciIrpNotSupported},
{IRP_UPWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_UPWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported},
{IRP_DOWNWARD, PciIrpNotSupported}
};
PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable =
{
IRP_MN_QUERY_LEGACY_BUS_INFORMATION,
PciFdoDispatchPnpTable,
IRP_MN_QUERY_POWER,
PciFdoDispatchPowerTable,
IRP_DOWNWARD,
PciIrpNotSupported,
IRP_DOWNWARD,
PciIrpNotSupported
};
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension)
{
ACPI_EVAL_INPUT_BUFFER InputBuffer;
PACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
ULONG Length;
NTSTATUS Status;
PAGED_CODE();
/* We should receive 4 parameters, per the HPP specification */
Length = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 4 * sizeof(ACPI_METHOD_ARGUMENT);
/* Allocate the buffer to hold the parameters */
OutputBuffer = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG);
if (!OutputBuffer) return;
/* Initialize the output and input buffers. The method is _HPP */
RtlZeroMemory(OutputBuffer, Length);
*(PULONG)InputBuffer.MethodName = 'PPH_';
InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
do
{
/* Send the IOCTL to the ACPI driver */
Status = PciSendIoctl(FdoExtension->PhysicalDeviceObject,
IOCTL_ACPI_EVAL_METHOD,
&InputBuffer,
sizeof(InputBuffer),
OutputBuffer,
Length);
if (!NT_SUCCESS(Status))
{
/* The method failed, check if we can salvage data from parent */
if (!PCI_IS_ROOT_FDO(FdoExtension))
{
/* Copy the root bus' hot plug parameters */
FdoExtension->HotPlugParameters = FdoExtension->ParentFdoExtension->HotPlugParameters;
}
/* Nothing more to do on this path */
break;
}
/* ACPI sent back some data. 4 parameters are expected in the output */
if (OutputBuffer->Count != 4) break;
/* HotPlug PCI Support not yet implemented */
UNIMPLEMENTED;
while (TRUE);
} while (FALSE);
/* Free the buffer and return */
ExFreePoolWithTag(OutputBuffer, 0);
}
VOID
NTAPI
PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension,
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
/* Initialize the extension */
RtlZeroMemory(FdoExtension, sizeof(PCI_FDO_EXTENSION));
/* Setup the common fields */
FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject;
FdoExtension->FunctionalDeviceObject = DeviceObject;
FdoExtension->ExtensionType = PciFdoExtensionType;
FdoExtension->PowerState.CurrentSystemState = PowerSystemWorking;
FdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
FdoExtension->IrpDispatchTable = &PciFdoDispatchTable;
/* Initialize the extension locks */
KeInitializeEvent(&FdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE);
KeInitializeEvent(&FdoExtension->ChildListLock, SynchronizationEvent, TRUE);
/* Initialize the default state */
PciInitializeState(FdoExtension);
}
NTSTATUS
NTAPI
PciAddDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
/* This function is not yet implemented */
UNIMPLEMENTED;
while (TRUE);
return STATUS_SUCCESS;
PCM_RESOURCE_LIST Descriptor;
PDEVICE_OBJECT AttachedTo;
PPCI_FDO_EXTENSION FdoExtension;
PPCI_FDO_EXTENSION ParentExtension;
PDEVICE_OBJECT DeviceObject;
UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
NTSTATUS Status;
HANDLE KeyHandle;
UNICODE_STRING ValueName;
ULONG ResultLength;
PAGED_CODE();
DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n",
PhysicalDeviceObject, &PhysicalDeviceObject->DriverObject->DriverName);
/* Zero out variables so failure path knows what to do */
AttachedTo = NULL;
do
{
/* Check if there's already a device extension for this bus */
ParentExtension = PciFindParentPciFdoExtension(PhysicalDeviceObject,
&PciGlobalLock);
if (ParentExtension)
{
/* More than one PCI bus, this is not expected yet */
UNIMPLEMENTED;
while (TRUE);
}
/* Create the FDO for the bus */
Status = IoCreateDevice(DriverObject,
sizeof(PCI_FDO_EXTENSION),
NULL,
FILE_DEVICE_BUS_EXTENDER,
0,
0,
&DeviceObject);
if (!NT_SUCCESS(Status)) break;
/* Initialize the extension for the FDO */
FdoExtension = DeviceObject->DeviceExtension;
PciInitializeFdoExtensionCommonFields(DeviceObject->DeviceExtension,
DeviceObject,
PhysicalDeviceObject);
/* Attach to the root PDO */
Status = STATUS_NO_SUCH_DEVICE;
AttachedTo = IoAttachDeviceToDeviceStack(DeviceObject,
PhysicalDeviceObject);
ASSERT(AttachedTo != NULL);
if (!AttachedTo) break;
FdoExtension->AttachedDeviceObject = AttachedTo;
if (ParentExtension)
{
/* More than one PCI bus, this is not expected yet */
UNIMPLEMENTED;
while (TRUE);
}
else
{
/* Query the boot configuration */
Status = PciGetDeviceProperty(PhysicalDeviceObject,
DevicePropertyBootConfiguration,
(PVOID*)&Descriptor);
if (!NT_SUCCESS(Status))
{
/* No configuration has been set */
Descriptor = NULL;
}
else
{
/* Root PDO in ReactOS does not assign boot resources */
UNIMPLEMENTED;
while (TRUE);
}
if (Descriptor)
{
/* Root PDO in ReactOS does not assign boot resources */
UNIMPLEMENTED;
while (TRUE);
}
else
{
/* Default configuration isn't the normal path on Windows */
if (PciBreakOnDefault)
{
/* If a second bus is found and there's still no data, crash */
KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL,
0xDEAD0010u,
(ULONG_PTR)DeviceObject,
0,
0);
}
/* Warn that a default configuration will be used, and set bus 0 */
DPRINT1("PCI Will use default configuration.\n");
PciBreakOnDefault = TRUE;
FdoExtension->BaseBus = 0;
}
/* This is the root bus */
FdoExtension->BusRootFdoExtension = FdoExtension;
}
/* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */
Status = PciGetConfigHandlers(FdoExtension);
if (!NT_SUCCESS(Status)) break;
/* Initialize all the supported PCI arbiters */
Status = PciInitializeArbiters(FdoExtension);
if (!NT_SUCCESS(Status)) break;
/* This is a real FDO, insert it into the list */
FdoExtension->Fake = FALSE;
PciInsertEntryAtTail(&PciFdoExtensionListHead,
FdoExtension,
&PciGlobalLock);
/* Open the device registry key so that we can query the errata flags */
IoOpenDeviceRegistryKey(DeviceObject,
PLUGPLAY_REGKEY_DEVICE,
KEY_ALL_ACCESS,
&KeyHandle),
/* Open the value that contains errata flags for this bus instance */
RtlInitUnicodeString(&ValueName, L"HackFlags");
Status = ZwQueryValueKey(KeyHandle,
&ValueName,
KeyValuePartialInformation,
ValueInfo,
sizeof(Buffer),
&ResultLength);
ZwClose(KeyHandle);
if (NT_SUCCESS(Status))
{
/* Make sure the data is of expected type and size */
if ((ValueInfo->Type == REG_DWORD) &&
(ValueInfo->DataLength == sizeof(ULONG)))
{
/* Read the flags for this bus */
FdoExtension->BusHackFlags = *(PULONG)&ValueInfo->Data;
}
}
/* Query ACPI for PCI HotPlug Support */
PciGetHotPlugParameters(FdoExtension);
/* The Bus FDO is now initialized */
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
DPRINT1("PCI Root FDO Added: %p %p\n", DeviceObject, FdoExtension);
return STATUS_SUCCESS;
} while (FALSE);
/* This is the failure path */
ASSERT(!NT_SUCCESS(Status));
if (AttachedTo) IoDetachDevice(AttachedTo);
if (DeviceObject) IoDeleteDevice(DeviceObject);
return Status;
}
/* EOF */

View file

@ -14,6 +14,11 @@
/* GLOBALS ********************************************************************/
PPCI_INTERFACE PciInterfaces[] =
{
NULL
};
/* FUNCTIONS ******************************************************************/
/* EOF */

View file

@ -17,12 +17,24 @@
#include "halfuncs.h"
#include "rtlfuncs.h"
#include "vffuncs.h"
#include "bugcodes.h"
//
// Tag used in all pool allocations (Pci Bus)
//
#define PCI_POOL_TAG 'BicP'
//
// Checks if the specified FDO is the FDO for the Root PCI Bus
//
#define PCI_IS_ROOT_FDO(x) ((x)->BusRootFdoExtension == x)
//
// Assertions to make sure we are dealing with the right kind of extension
//
#define ASSERT_FDO(x) ASSERT((x)->ExtensionType == PciFdoExtensionType);
#define ASSERT_PDO(x) ASSERT((x)->ExtensionType == PciPdoExtensionType);
//
// PCI Hack Entry Name Lengths
//
@ -32,10 +44,62 @@
#define PCI_HACK_ENTRY_FULL_SIZE sizeof(L"VVVVddddssssIIIIRR") // 36
//
// PCI Hack Entry Information
// PCI Hack Entry Flags
//
#define PCI_HACK_HAS_REVISION_INFO 0x01
#define PCI_HACK_HAS_SUBSYSTEM_INFO 0x02
//
// Device Extension, Interface, Translator and Arbiter Signatures
//
typedef enum _PCI_SIGNATURE
{
PciPdoExtensionType = '0Pci',
PciFdoExtensionType = '1Pci',
PciArb_Io = '2Pci',
PciArb_Memory = '3Pci',
PciArb_Interrupt = '4Pci',
PciArb_BusNumber = '5Pci',
PciTrans_Interrupt = '6Pci',
PciInterface_BusHandler = '7Pci',
PciInterface_IntRouteHandler = '8Pci',
PciInterface_PciCb = '9Pci',
PciInterface_LegacyDeviceDetection = ':Pci',
PciInterface_PmeHandler = ';Pci',
PciInterface_DevicePresent = '<Pci',
PciInterface_NativeIde = '=Pci',
PciInterface_AgpTarget = '>Pci',
PciInterface_Location = '?Pci'
} PCI_SIGNATURE, *PPCI_SIGNATURE;
//
// Device Extension Logic States
//
typedef enum _PCI_STATE
{
PciNotStarted,
PciStarted,
PciDeleted,
PciStopped,
PciSurpriseRemoved,
PciSynchronizedOperation,
PciMaxObjectState
} PCI_STATE;
//
// IRP Dispatch Logic Style
//
typedef enum _PCI_DISPATCH_STYLE
{
IRP_COMPLETE,
IRP_DOWNWARD,
IRP_UPWARD,
IRP_DISPATCH,
} PCI_DISPATCH_STYLE;
//
// PCI Hack Entry Information
//
typedef struct _PCI_HACK_ENTRY
{
USHORT VendorID;
@ -47,6 +111,165 @@ typedef struct _PCI_HACK_ENTRY
UCHAR Flags;
} PCI_HACK_ENTRY, *PPCI_HACK_ENTRY;
//
// Power State Information for Device Extension
//
typedef struct _PCI_POWER_STATE
{
SYSTEM_POWER_STATE CurrentSystemState;
DEVICE_POWER_STATE CurrentDeviceState;
SYSTEM_POWER_STATE SystemWakeLevel;
DEVICE_POWER_STATE DeviceWakeLevel;
DEVICE_POWER_STATE SystemStateMapping[7];
PIRP WaitWakeIrp;
PVOID SavedCancelRoutine;
LONG Paging;
LONG Hibernate;
LONG CrashDump;
} PCI_POWER_STATE, *PPCI_POWER_STATE;
//
// Internal PCI Lock Structure
//
typedef struct _PCI_LOCK
{
LONG Atom;
BOOLEAN OldIrql;
} PCI_LOCK, *PPCI_LOCK;
//
// Device Extension for a Bus FDO
//
typedef struct _PCI_FDO_EXTENSION
{
SINGLE_LIST_ENTRY List;
ULONG ExtensionType;
struct _PCI_MJ_DISPATCH_TABLE *IrpDispatchTable;
BOOLEAN DeviceState;
BOOLEAN TentativeNextState;
KEVENT SecondaryExtLock;
PDEVICE_OBJECT PhysicalDeviceObject;
PDEVICE_OBJECT FunctionalDeviceObject;
PDEVICE_OBJECT AttachedDeviceObject;
KEVENT ChildListLock;
struct _PCI_PDO_EXTENSION *ChildPdoList;
struct _PCI_FDO_EXTENSION *BusRootFdoExtension;
struct _PCI_FDO_EXTENSION *ParentFdoExtension;
struct _PCI_PDO_EXTENSION *ChildBridgePdoList;
PPCI_BUS_INTERFACE_STANDARD PciBusInterface;
BOOLEAN MaxSubordinateBus;
BUS_HANDLER *BusHandler;
BOOLEAN BaseBus;
BOOLEAN Fake;
BOOLEAN ChildDelete;
BOOLEAN Scanned;
BOOLEAN ArbitersInitialized;
BOOLEAN BrokenVideoHackApplied;
BOOLEAN Hibernated;
PCI_POWER_STATE PowerState;
SINGLE_LIST_ENTRY SecondaryExtension;
LONG ChildWaitWakeCount;
PPCI_COMMON_CONFIG PreservedConfig;
PCI_LOCK Lock;
struct
{
BOOLEAN Acquired;
BOOLEAN CacheLineSize;
BOOLEAN LatencyTimer;
BOOLEAN EnablePERR;
BOOLEAN EnableSERR;
} HotPlugParameters;
LONG BusHackFlags;
} PCI_FDO_EXTENSION, *PPCI_FDO_EXTENSION;
//
// IRP Dispatch Function Type
//
typedef NTSTATUS (NTAPI *PCI_DISPATCH_FUNCTION)(
IN PIRP Irp,
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_FDO_EXTENSION DeviceExtension
);
//
// IRP Dispatch Minor Table
//
typedef struct _PCI_MN_DISPATCH_TABLE
{
PCI_DISPATCH_STYLE DispatchStyle;
PCI_DISPATCH_FUNCTION DispatchFunction;
} PCI_MN_DISPATCH_TABLE, *PPCI_MN_DISPATCH_TABLE;
//
// IRP Dispatch Major Table
//
typedef struct _PCI_MJ_DISPATCH_TABLE
{
ULONG PnpIrpMaximumMinorFunction;
PPCI_MN_DISPATCH_TABLE PnpIrpDispatchTable;
ULONG PowerIrpMaximumMinorFunction;
PPCI_MN_DISPATCH_TABLE PowerIrpDispatchTable;
PCI_DISPATCH_STYLE SystemControlIrpDispatchStyle;
PCI_DISPATCH_FUNCTION SystemControlIrpDispatchFunction;
PCI_DISPATCH_STYLE OtherIrpDispatchStyle;
PCI_DISPATCH_FUNCTION OtherIrpDispatchFunction;
} PCI_MJ_DISPATCH_TABLE, *PPCI_MJ_DISPATCH_TABLE;
//
// Generic PCI Interface Constructor and Initializer
//
struct _PCI_INTERFACE;
typedef NTSTATUS (NTAPI *PCI_INTERFACE_CONSTRUCTOR)(
IN PPCI_FDO_EXTENSION DeviceExtension,
IN PVOID Instance,
IN PVOID InterfaceData,
IN USHORT Version,
IN USHORT Size,
IN PINTERFACE Interface
);
typedef NTSTATUS (NTAPI *PCI_INTERFACE_INITIALIZER)(
IN PVOID Instance
);
//
// Generic PCI Interface (Interface, Translator, Arbiter)
//
typedef struct _PCI_INTERFACE
{
LPGUID InterfaceType;
USHORT MinSize;
USHORT MinVersion;
USHORT MaxVersion;
USHORT Flags;
LONG ReferenceCount;
PCI_SIGNATURE Signature;
PCI_INTERFACE_CONSTRUCTOR Constructor;
PCI_INTERFACE_INITIALIZER Initializer;
} PCI_INTERFACE, *PPCI_INTERFACE;
//
// Generic Secondary Extension Instance Header (Interface, Translator, Arbiter)
//
typedef struct PCI_SECONDARY_EXTENSION
{
SINGLE_LIST_ENTRY List;
PCI_SIGNATURE ExtensionType;
PVOID Destructor;
} PCI_SECONDARY_EXTENSION, *PPCI_SECONDARY_EXTENSION;
//
// PCI Arbiter Instance
//
typedef struct PCI_ARBITER_INSTANCE
{
PCI_SECONDARY_EXTENSION Header;
PPCI_INTERFACE Interface;
PPCI_FDO_EXTENSION BusFdoExtension;
WCHAR InstanceName[24];
//ARBITER_INSTANCE CommonInstance; FIXME: Need Arbiter Headers
} PCI_ARBITER_INSTANCE, *PPCI_ARBITER_INSTANCE;
//
// IRP Dispatch Routines
//
@ -57,6 +280,14 @@ PciDispatchIrp(
IN PIRP Irp
);
NTSTATUS
NTAPI
PciIrpNotSupported(
IN PIRP Irp,
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_FDO_EXTENSION DeviceExtension
);
//
// Bus FDO Routines
//
@ -136,4 +367,82 @@ PciGetRegistryValue(
OUT PULONG OutputLength
);
PPCI_FDO_EXTENSION
NTAPI
PciFindParentPciFdoExtension(
IN PDEVICE_OBJECT DeviceObject,
IN PKEVENT Lock
);
VOID
NTAPI
PciInsertEntryAtTail(
IN PSINGLE_LIST_ENTRY ListHead,
IN PPCI_FDO_EXTENSION DeviceExtension,
IN PKEVENT Lock
);
NTSTATUS
NTAPI
PciGetDeviceProperty(
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
OUT PVOID *OutputBuffer
);
NTSTATUS
NTAPI
PciSendIoctl(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
IN PVOID OutputBuffer,
IN ULONG OutputBufferLength
);
VOID
NTAPI
PcipLinkSecondaryExtension(
IN PSINGLE_LIST_ENTRY List,
IN PVOID Lock,
IN PPCI_SECONDARY_EXTENSION SecondaryExtension,
IN PCI_SIGNATURE ExtensionType,
IN PVOID Destructor
);
//
// Configuration Routines
//
NTSTATUS
NTAPI
PciGetConfigHandlers(
IN PPCI_FDO_EXTENSION FdoExtension
);
//
// State Machine Logic Transition Routines
//
VOID
NTAPI
PciInitializeState(
IN PPCI_FDO_EXTENSION DeviceExtension
);
//
// Arbiter Support
//
NTSTATUS
NTAPI
PciInitializeArbiters(
IN PPCI_FDO_EXTENSION FdoExtension
);
//
// External Resources
//
extern SINGLE_LIST_ENTRY PciFdoExtensionListHead;
extern KEVENT PciGlobalLock;
extern PPCI_INTERFACE PciInterfaces[];
/* EOF */

View file

@ -14,6 +14,154 @@
/* GLOBALS ********************************************************************/
BOOLEAN PciAssignBusNumbers;
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension)
{
PDEVICE_OBJECT AttachedDevice;
IO_STATUS_BLOCK IoStatusBlock;
KEVENT Event;
NTSTATUS Status;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
PPCI_BUS_INTERFACE_STANDARD PciInterface;
PAGED_CODE();
ASSERT(PCI_IS_ROOT_FDO(FdoExtension));
/* Allocate space for the inteface */
PciInterface = ExAllocatePoolWithTag(NonPagedPool,
sizeof(PCI_BUS_INTERFACE_STANDARD),
PCI_POOL_TAG);
if (!PciInterface) return STATUS_INSUFFICIENT_RESOURCES;
/* Get the device the PDO is attached to, should be the Root (ACPI) */
AttachedDevice = IoGetAttachedDeviceReference(FdoExtension->PhysicalDeviceObject);
/* Build an IRP for this request */
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
AttachedDevice,
NULL,
0,
NULL,
&Event,
&IoStatusBlock);
if (Irp)
{
/* Initialize the default PnP response */
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
/* Make it a Query Interface IRP */
IoStackLocation = IoGetNextIrpStackLocation(Irp);
ASSERT(IoStackLocation->MajorFunction == IRP_MJ_PNP);
IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_PCI_BUS_INTERFACE_STANDARD;
IoStackLocation->Parameters.QueryInterface.Size = sizeof(GUID_PCI_BUS_INTERFACE_STANDARD);
IoStackLocation->Parameters.QueryInterface.Version = PCI_BUS_INTERFACE_STANDARD_VERSION;
IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)PciInterface;
IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL;
/* Send it to the root PDO */
Status = IoCallDriver(AttachedDevice, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for completion */
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = Irp->IoStatus.Status;
}
/* Check if an interface was returned */
if (!NT_SUCCESS(Status))
{
/* No interface was returned by the root PDO */
FdoExtension->PciBusInterface = NULL;
ExFreePoolWithTag(PciInterface, 0);
}
else
{
/* An interface was returned, save it */
FdoExtension->PciBusInterface = PciInterface;
}
/* Dereference the device object because we took a reference earlier */
ObfDereferenceObject(AttachedDevice);
}
else
{
/* Failure path, dereference the device object and set failure code */
if (AttachedDevice) ObfDereferenceObject(AttachedDevice);
ExFreePoolWithTag(PciInterface, 0);
Status = STATUS_INSUFFICIENT_RESOURCES;
}
/* Return status code to caller */
return Status;
}
NTSTATUS
NTAPI
PciGetConfigHandlers(IN PPCI_FDO_EXTENSION FdoExtension)
{
PBUS_HANDLER BusHandler;
NTSTATUS Status;
ASSERT(FdoExtension->BusHandler == NULL);
/* Check if this is the FDO for the root bus */
if (PCI_IS_ROOT_FDO(FdoExtension))
{
/* Query the PCI Bus Interface that ACPI exposes */
ASSERT(FdoExtension->PciBusInterface == NULL);
Status = PciQueryForPciBusInterface(FdoExtension);
if (!NT_SUCCESS(Status))
{
/* No ACPI, so Bus Numbers should be maintained by BIOS */
ASSERT(!PciAssignBusNumbers);
}
else
{
/* ACPI detected, PCI Bus Driver will reconfigure bus numbers*/
PciAssignBusNumbers = TRUE;
}
}
else
{
/* Check if the root bus already has the interface set up */
if (FdoExtension->BusRootFdoExtension->PciBusInterface)
{
/* Nothing for this FDO to do */
return STATUS_SUCCESS;
}
/* Fail into case below so we can query the HAL interface */
Status = STATUS_NOT_SUPPORTED;
}
/* If the ACPI PCI Bus Interface couldn't be obtained, try the HAL */
if (!NT_SUCCESS(Status))
{
/* Bus number assignment should be static */
ASSERT(Status == STATUS_NOT_SUPPORTED);
ASSERT(!PciAssignBusNumbers);
/* Call the HAL to obtain the bus handler for PCI */
BusHandler = HalReferenceHandlerForBus(PCIBus, FdoExtension->BaseBus);
FdoExtension->BusHandler = BusHandler;
/* Fail if the HAL does not have a PCI Bus Handler for this bus */
if (!BusHandler) return STATUS_INVALID_DEVICE_REQUEST;
}
/* Appropriate interface was obtained */
return STATUS_SUCCESS;
}
/* EOF */

View file

@ -16,4 +16,13 @@
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension)
{
/* Set the initial state */
DeviceExtension->DeviceState = PciNotStarted;
DeviceExtension->TentativeNextState = PciNotStarted;
}
/* EOF */

View file

@ -333,4 +333,226 @@ PciBuildDefaultExclusionLists(VOID)
return Status;
}
PPCI_FDO_EXTENSION
NTAPI
PciFindParentPciFdoExtension(IN PDEVICE_OBJECT DeviceObject,
IN PKEVENT Lock)
{
PPCI_FDO_EXTENSION FoundExtension;
/* Assume we'll find nothing */
FoundExtension = NULL;
/* Check if a lock was specified */
if (Lock)
{
/* Wait for the lock to be released */
KeEnterCriticalRegion();
KeWaitForSingleObject(Lock, Executive, KernelMode, FALSE, NULL);
}
/* Now search for the extension */
if (PciFdoExtensionListHead.Next)
{
/* This case should not be hit yet */
UNIMPLEMENTED;
while (TRUE);
}
/* Check if we had acquired a lock previously */
if (Lock)
{
/* Release it */
KeSetEvent(Lock, IO_NO_INCREMENT, FALSE);
KeLeaveCriticalRegion();
}
/* Return which extension was found, if any */
return FoundExtension;
}
VOID
NTAPI
PciInsertEntryAtTail(IN PSINGLE_LIST_ENTRY ListHead,
IN PPCI_FDO_EXTENSION DeviceExtension,
IN PKEVENT Lock)
{
PSINGLE_LIST_ENTRY NextEntry;
PAGED_CODE();
/* Check if a lock was specified */
if (Lock)
{
/* Wait for the lock to be released */
KeEnterCriticalRegion();
KeWaitForSingleObject(Lock, Executive, KernelMode, FALSE, NULL);
}
/* Loop the list until we get to the end, then insert this entry there */
for (NextEntry = ListHead; NextEntry->Next; NextEntry = NextEntry->Next);
NextEntry->Next = &DeviceExtension->List;
/* Check if we had acquired a lock previously */
if (Lock)
{
/* Release it */
KeSetEvent(Lock, IO_NO_INCREMENT, FALSE);
KeLeaveCriticalRegion();
}
}
VOID
NTAPI
PciInsertEntryAtHead(IN PSINGLE_LIST_ENTRY ListHead,
IN PSINGLE_LIST_ENTRY Entry,
IN PKEVENT Lock)
{
PAGED_CODE();
/* Check if a lock was specified */
if (Lock)
{
/* Wait for the lock to be released */
KeEnterCriticalRegion();
KeWaitForSingleObject(Lock, Executive, KernelMode, FALSE, NULL);
}
/* Make the entry point to the current head and make the head point to it */
Entry->Next = ListHead->Next;
ListHead->Next = Entry;
/* Check if we had acquired a lock previously */
if (Lock)
{
/* Release it */
KeSetEvent(Lock, IO_NO_INCREMENT, FALSE);
KeLeaveCriticalRegion();
}
}
VOID
NTAPI
PcipLinkSecondaryExtension(IN PSINGLE_LIST_ENTRY List,
IN PVOID Lock,
IN PPCI_SECONDARY_EXTENSION SecondaryExtension,
IN PCI_SIGNATURE ExtensionType,
IN PVOID Destructor)
{
PAGED_CODE();
/* Setup the extension data, and insert it into the primary's list */
SecondaryExtension->ExtensionType = ExtensionType;
SecondaryExtension->Destructor = Destructor;
PciInsertEntryAtHead(List, &SecondaryExtension->List, Lock);
}
NTSTATUS
NTAPI
PciGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
OUT PVOID *OutputBuffer)
{
NTSTATUS Status;
ULONG BufferLength, ResultLength;
PVOID Buffer;
do
{
/* Query the requested property size */
Status = IoGetDeviceProperty(DeviceObject,
DeviceProperty,
0,
NULL,
&BufferLength);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
/* Call should've failed with buffer too small! */
DPRINT1("PCI - Unexpected status from GetDeviceProperty, saw %08X, expected %08X.\n",
Status,
STATUS_BUFFER_TOO_SMALL);
*OutputBuffer = NULL;
ASSERTMSG(FALSE, "PCI Successfully did the impossible!");
break;
}
/* Allocate the required buffer */
Buffer = ExAllocatePoolWithTag(PagedPool, BufferLength, 'BicP');
if (!Buffer)
{
/* No memory, fail the request */
DPRINT1("PCI - Failed to allocate DeviceProperty buffer (%d bytes).\n", BufferLength);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* Do the actual property query call */
Status = IoGetDeviceProperty(DeviceObject,
DeviceProperty,
BufferLength,
Buffer,
&ResultLength);
if (!NT_SUCCESS(Status)) break;
/* Return the buffer to the caller */
ASSERT(BufferLength == ResultLength);
*OutputBuffer = Buffer;
return STATUS_SUCCESS;
} while (FALSE);
/* Failure path */
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
PciSendIoctl(IN PDEVICE_OBJECT DeviceObject,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
IN PVOID OutputBuffer,
IN ULONG OutputBufferLength)
{
PIRP Irp;
NTSTATUS Status;
KEVENT Event;
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_OBJECT AttachedDevice;
PAGED_CODE();
/* Initialize the pending IRP event */
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
/* Get a reference to the root PDO (ACPI) */
AttachedDevice = IoGetAttachedDeviceReference(DeviceObject);
if (!AttachedDevice) return STATUS_INVALID_PARAMETER;
/* Build the requested IOCTL IRP */
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
AttachedDevice,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
0,
&Event,
&IoStatusBlock);
if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
/* Send the IOCTL to the driver */
Status = IoCallDriver(AttachedDevice, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for a response */
KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = Irp->IoStatus.Status;
}
/* Take away the reference we took and return the result to the caller */
ObDereferenceObject(AttachedDevice);
return Status;
}
/* EOF */