Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2406 lines
60 KiB

/*++
Copyright (c) 1996-2000 Microsoft Corporation
Module Name:
pcip.h
Abstract:
This module contains local definitions for PCI.SYS.
Author:
Andrew Thornton (andrewth) 25-Jan-2000
Revision History:
--*/
#if !defined(_PCIP_H)
#define _PCIP_H
//
// Disable warnings of features used by the standard headers
//
// Disable warning C4214: nonstandard extension used : bit field types other than int
// Disable warning C4201: nonstandard extension used : nameless struct/union
// Disable warning C4115: named type definition in parentheses
// Disable warning C4127: conditional expression is constant
//
#pragma warning(disable:4214 4201 4115 4127)
#define _NTDRIVER_
#define _NTSRV_
#define _NTDDK_
#define InitSafeBootMode TempInitSafeBootMode
#include "ntos.h"
#undef InitSafeBootMode
#include "strsafe.h"
#include "pci.h"
#include "wdmguid.h"
#include "zwapi.h"
#include "pciirqmp.h"
#include "arbiter.h"
#include "acpiioct.h"
#include "pciintrf.h"
#include "pcicodes.h"
#include "pciverifier.h"
#include "acpitabl.h"
//
// regstr.h uses things of type WORD, which isn't around in kernel mode.
//
#define _IN_KERNEL_
#include "regstr.h"
//
// Pragmas to disable /W4 warnings so PCI can be compiled /W4
//
// Disable warning C4057; X differs in indirection to slightly different base types from Y
// Disable warning C4244; '+='/'-=' : conversion from 'int' to 'X', possible loss of data
// Disable warning C4100: 'X' : unreferenced formal parameter
#pragma warning(disable: 4057 4244 4100)
//
// It seems that anything to do with the definitions of GUIDs is
// bogus.
//
typedef const GUID * PGUID;
#define PciCompareGuid(a,b) \
(RtlEqualMemory((PVOID)(a), (PVOID)(b), sizeof(GUID)))
//
// Internal constants.
//
#define PCI_CM_RESOURCE_VERSION 1
#define PCI_CM_RESOURCE_REVISION 1
#define PCI_MAX_CONFIG_TYPE (PCI_CARDBUS_BRIDGE_TYPE)
//
// Internal bug codes.
//
#define PCI_BUGCODE_TOO_MANY_CONFIG_GUESSES 0xdead0010
//
// Internal Controls
//
#define PCI_BOOT_CONFIG_PREFERRED 1
#define PCIIDE_HACKS 1
#define PCI_NT50_BETA1_HACKS 1
#define PCI_DISABLE_LAST_CHANCE_INTERFACES 1
#define MSI_SUPPORTED 0
#define PCI_NO_MOVE_MODEM_IN_TOSHIBA 1
//
// Systemwide hack flags. These flags are a bitmask that can be set to zero so
// as to eliminate support for the hack.
//
#define PCIFLAG_IGNORE_PREFETCHABLE_MEMORY_AT_ROOT_HACK 0x00000001
//
// Video Hacks
//
#define PCI_S3_HACKS 1
#define PCI_CIRRUS_54XX_HACK 1
#define PCI_IS_ATI_M1(_PdoExtension) \
((_PdoExtension)->VendorId == 0x1002 \
&& ((_PdoExtension)->DeviceId == 0x4C42 \
|| (_PdoExtension)->DeviceId == 0x4C44 \
|| (_PdoExtension)->DeviceId == 0x4C49 \
|| (_PdoExtension)->DeviceId == 0x4C4D \
|| (_PdoExtension)->DeviceId == 0x4C4E \
|| (_PdoExtension)->DeviceId == 0x4C50 \
|| (_PdoExtension)->DeviceId == 0x4C51 \
|| (_PdoExtension)->DeviceId == 0x4C52 \
|| (_PdoExtension)->DeviceId == 0x4C53))
#define INTEL_ICH_HACKS 1
#if INTEL_ICH_HACKS
#define PCI_IS_INTEL_ICH(_PdoExtension) \
((_PdoExtension)->VendorId == 0x8086 \
&& ((_PdoExtension)->DeviceId == 0x2418 \
|| (_PdoExtension)->DeviceId == 0x2428 \
|| (_PdoExtension)->DeviceId == 0x244E \
|| (_PdoExtension)->DeviceId == 0x2448))
#else
#define PCI_IS_INTEL_ICH(_PdoExtension) FALSE
#endif
//
// Translatable resources
//
#define ADDRESS_SPACE_MEMORY 0x0
#define ADDRESS_SPACE_PORT 0x1
#define ADDRESS_SPACE_USER_MEMORY 0x2
#define ADDRESS_SPACE_USER_PORT 0x3
#define ADDRESS_SPACE_DENSE_MEMORY 0x4
#define ADDRESS_SPACE_USER_DENSE_MEMORY 0x6
//
// Add our tag signature
//
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool( t, s ) ExAllocatePoolWithTag( (t), (s), 'BicP' )
//
// Lock and Unlock
//
typedef struct _PCI_LOCK {
KSPIN_LOCK Atom;
KIRQL OldIrql;
#if DBG
PUCHAR File;
ULONG Line;
#endif
} PCI_LOCK, *PPCI_LOCK;
#if DBG
#define PCI_LOCK_OBJECT(x) \
(x)->Lock.File = __FILE__, \
(x)->Lock.Line = __LINE__, \
KeAcquireSpinLock(&(x)->Lock.Atom, &(x)->Lock.OldIrql)
#else
#define PCI_LOCK_OBJECT(x) \
KeAcquireSpinLock(&(x)->Lock.Atom, &(x)->Lock.OldIrql)
#endif
#define PCI_UNLOCK_OBJECT(x) \
KeReleaseSpinLock(&(x)->Lock.Atom, (x)->Lock.OldIrql)
#define PciAcquireGlobalLock() \
ExAcquireFastMutex(&PciGlobalLock)
#define PciReleaseGlobalLock() \
ExReleaseFastMutex(&PciGlobalLock)
//
// PCM_PARTIAL_RESOURCE_DESCRIPTOR
// PciFirstCmResource(
// PCM_RESOURCE_LIST List
// )
//
// Routine Description:
//
// Returns the address of the first CM PARTIAL RESOURCE DESCRIPTOR
// in the given CM RESOURCE LIST.
//
#define PciFirstCmResource(x) \
(x)->List[0].PartialResourceList.PartialDescriptors
//
// ULONG
// PciGetConfigurationType(
// PPCI_COMMON_CONFIG x
// )
//
// Routine Description:
//
// Returns the configuration type subfield from the HeaderType
// field in PCI Configuration Space.
//
#define PciGetConfigurationType(x) PCI_CONFIGURATION_TYPE(x)
//
// PPCI_FDO_EXTENSION
// PCI_PARENT_FDO(
// PPCI_PDO_EXTENSION x
// )
//
// Routine Description:
//
// Returns a pointer to the FDO extension that created PDO x as a result
// of enumeration. That is, the FDO extension of the bus that owns this
// device.
//
#define PCI_PARENT_FDOX(x) ((x)->ParentFdoExtension)
//
// PPCI_FDO_EXTENSION
// PCI_ROOT_FDOX(
// PPCI_PDO_EXTENSION x
// )
//
// Routine Description:
//
// Returns a pointer to the FDO extension for the root bus (CPU-PCI Bridge)
// that this device is situated under.
//
#define PCI_ROOT_FDOX(x) ((x)->ParentFdoExtension->BusRootFdoExtension)
//
// PDEVICE_OBJECT
// PCI_PARENT_PDO(
// PPCI_PDO_EXTENSION x
// )
//
// Routine Description:
//
// Returns a pointer to the PDO for the parent bus.
//
#define PCI_PARENT_PDO(x) ((x)->ParentFdoExtension->PhysicalDeviceObject)
//
// PPCI_PDO_EXTENSION
// PCI_BRIDGE_PDO(
// PPCI_FDO_EXTENSION x
// )
//
// Routine Description:
//
// Returns a pointer to the PDO for the bridge given its FDO
//
#define PCI_BRIDGE_PDO(x) ((PPCI_PDO_EXTENSION)((x)->PhysicalDeviceObject->DeviceExtension))
//
// PPCI_FDO_EXTENSION
// PCI_BRIDGE_FDO(
// PPCI_PDO_EXTENSION x
// )
//
// Routine Description:
//
// Returns a pointer to the FDO for the bridge given its PDO
//
#define PCI_BRIDGE_FDO(x) ((PPCI_FDO_EXTENSION)((x)->BridgeFdoExtension))
//
// BOOLEAN
// PCI_IS_ROOT_FDO(
// PPCI_FDO_EXTENSION x
// )
//
// Routine Description:
//
// Returns TRUE if x is an FDO for a PCI ROOT bus.
//
#define PCI_IS_ROOT_FDO(x) ((BOOLEAN)((x) == (x)->BusRootFdoExtension))
//
// BOOLEAN
// PCI_PDO_ON_ROOT(
// PPCI_PDO_EXTENSION x
// )
//
// Routine Description:
//
#define PCI_PDO_ON_ROOT(x) ((BOOLEAN)PCI_IS_ROOT_FDO(PCI_PARENT_FDOX(x)))
//
// UCHAR
// PCI_DEVFUNC(
// PPCI_PDO_EXTENSION x
// )
//
// Routine Description:
//
// Returns the 5 bit device number and 3 bit function number for this
// device as a single 8 bit quantity.
//
#define PCI_DEVFUNC(x) (((x)->Slot.u.bits.DeviceNumber << 3) | \
(x)->Slot.u.bits.FunctionNumber)
//
//
// VOID
// PciConstStringToUnicodeString(
// OUT PUNICODE_STRING u,
// IN PCWSTR p
// )
//
//
#define PciConstStringToUnicodeString(u, p) \
(u)->Length = ((u)->MaximumLength = sizeof((p))) - sizeof(WCHAR); \
(u)->Buffer = (p)
//
// Name of the volative key under the DeviceParameters key where data that needs
// to be persistent accross removes, but NOT reboots is stored
//
#define BIOS_CONFIG_KEY_NAME L"BiosConfig"
//
// Assert this is a device object created by PCI
//
#define ASSERT_PCI_DEVICE_OBJECT(_DeviceObject) \
PCI_ASSERT((_DeviceObject)->DriverObject == PciDriverObject)
#define ASSERT_MUTEX_HELD(x)
//
// IRPs can be handled the following ways
//
typedef enum _PCI_DISPATCH_STYLE {
IRP_COMPLETE, // Complete IRP, adjust status as neccessary
IRP_DOWNWARD, // Dispatch on the way down, adjust status as neccessary
IRP_UPWARD, // Dispatch on the way up, adjust status as neccessary
IRP_DISPATCH // Dispatch downward, don't touch afterwards
} PCI_DISPATCH_STYLE;
//
// The following routines are dispatched to depending on header type.
//
typedef
VOID
(*PMASSAGEHEADERFORLIMITSDETERMINATION)(
IN struct _PCI_CONFIGURABLE_OBJECT *This
);
typedef
VOID
(*PSAVELIMITS)(
IN struct _PCI_CONFIGURABLE_OBJECT *This
);
typedef
VOID
(*PSAVECURRENTSETTINGS)(
IN struct _PCI_CONFIGURABLE_OBJECT *This
);
typedef
VOID
(*PRESTORECURRENT)(
IN struct _PCI_CONFIGURABLE_OBJECT *This
);
typedef
VOID
(*PCHANGERESOURCESETTINGS)(
IN struct _PCI_PDO_EXTENSION * PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
typedef
VOID
(*PGETADDITIONALRESOURCEDESCRIPTORS)(
IN struct _PCI_PDO_EXTENSION * PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig,
IN PIO_RESOURCE_DESCRIPTOR Resource
);
typedef
NTSTATUS
(*PRESETDEVICE)(
IN struct _PCI_PDO_EXTENSION * PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
typedef struct {
PMASSAGEHEADERFORLIMITSDETERMINATION MassageHeaderForLimitsDetermination;
PRESTORECURRENT RestoreCurrent;
PSAVELIMITS SaveLimits;
PSAVECURRENTSETTINGS SaveCurrentSettings;
PCHANGERESOURCESETTINGS ChangeResourceSettings;
PGETADDITIONALRESOURCEDESCRIPTORS GetAdditionalResourceDescriptors;
PRESETDEVICE ResetDevice;
} PCI_CONFIGURATOR, *PPCI_CONFIGURATOR;
//
// Internal structure definitions follow
//
typedef enum {
PciBridgeIo = 0x10,
PciBridgeMem,
PciBridgePrefetch,
PciBridgeMaxPassThru
} PCI_BRIDGE_PASSTHRU;
typedef enum {
//
// Device Object Extension Types
//
PciPdoExtensionType = 'icP0',
PciFdoExtensionType,
//
// Arbitration Types. (These are also secondary extensions).
//
PciArb_Io,
PciArb_Memory,
PciArb_Interrupt,
PciArb_BusNumber,
//
// Translation Types. (These are also secondary extensions).
//
PciTrans_Interrupt,
//
// Other exposed interfaces.
//
PciInterface_BusHandler,
PciInterface_IntRouteHandler,
PciInterface_PciCb,
PciInterface_LegacyDeviceDetection,
PciInterface_PmeHandler,
PciInterface_DevicePresent,
PciInterface_NativeIde,
PciInterface_Location,
PciInterface_AgpTarget
} PCI_SIGNATURE;
#define PCI_EXTENSIONTYPE_FDO PciFdoExtensionType
#define PCI_EXTENSIONTYPE_PDO PciPdoExtensionType
typedef enum {
PciTypeUnknown,
PciTypeHostBridge,
PciTypePciBridge,
PciTypeCardbusBridge,
PciTypeDevice
} PCI_OBJECT_TYPE;
typedef enum {
PciPrivateUndefined,
PciPrivateBar,
PciPrivateIsaBar,
PciPrivateSkipList
} PCI_PRIVATE_RESOURCE_TYPES;
typedef
VOID
(*PSECONDARYEXTENSIONDESTRUCTOR)(
IN PVOID Extension
);
typedef struct {
SINGLE_LIST_ENTRY List;
PCI_SIGNATURE ExtensionType;
PSECONDARYEXTENSIONDESTRUCTOR Destructor;
} PCI_SECONDARY_EXTENSION, *PPCI_SECONDARY_EXTENSION;
//
// Define a structure to contain current and limit settings
// for any (currently defined) PCI header type.
//
// Currently type 0 defines the greatest number of possible
// resources but we shall do it programmatically anyway.
//
// Type 0 and type 1 also have a ROM base address, additionally,
// type 1 has three ranges that aren't included in its address
// count but should be.
//
#define PCI_TYPE0_RANGE_COUNT ((PCI_TYPE0_ADDRESSES) + 1)
#define PCI_TYPE1_RANGE_COUNT ((PCI_TYPE1_ADDRESSES) + 4)
#define PCI_TYPE2_RANGE_COUNT ((PCI_TYPE2_ADDRESSES) + 1)
#if PCI_TYPE0_RANGE_COUNT > PCI_TYPE1_RANGE_COUNT
#if PCI_TYPE0_RANGE_COUNT > PCI_TYPE2_RANGE_COUNT
#define PCI_MAX_RANGE_COUNT PCI_TYPE0_RANGE_COUNT
#else
#define PCI_MAX_RANGE_COUNT PCI_TYPE2_RANGE_COUNT
#endif
#else
#if PCI_TYPE1_RANGE_COUNT > PCI_TYPE2_RANGE_COUNT
#define PCI_MAX_RANGE_COUNT PCI_TYPE1_RANGE_COUNT
#else
#define PCI_MAX_RANGE_COUNT PCI_TYPE2_RANGE_COUNT
#endif
#endif
typedef union {
struct {
UCHAR Spare[4];
} type0;
struct {
UCHAR PrimaryBus;
UCHAR SecondaryBus;
UCHAR SubordinateBus;
BOOLEAN SubtractiveDecode:1;
BOOLEAN IsaBitSet:1;
BOOLEAN VgaBitSet:1;
BOOLEAN WeChangedBusNumbers:1;
BOOLEAN IsaBitRequired:1;
} type1;
struct {
UCHAR PrimaryBus;
UCHAR SecondaryBus;
UCHAR SubordinateBus;
BOOLEAN SubtractiveDecode:1;
BOOLEAN IsaBitSet:1;
BOOLEAN VgaBitSet:1;
BOOLEAN WeChangedBusNumbers:1;
BOOLEAN IsaBitRequired:1;
} type2;
} PCI_HEADER_TYPE_DEPENDENT;
typedef struct {
IO_RESOURCE_DESCRIPTOR Limit[PCI_MAX_RANGE_COUNT];
CM_PARTIAL_RESOURCE_DESCRIPTOR Current[PCI_MAX_RANGE_COUNT];
} PCI_FUNCTION_RESOURCES, *PPCI_FUNCTION_RESOURCES;
//
// Indices for the PCI_FUNCTION_RESOURCES arrays for different header types
//
#define PCI_DEVICE_BAR_0 0
#define PCI_DEVICE_BAR_1 1
#define PCI_DEVICE_BAR_2 2
#define PCI_DEVICE_BAR_3 3
#define PCI_DEVICE_BAR_4 4
#define PCI_DEVICE_BAR_5 5
#define PCI_DEVICE_BAR_ROM 6
#define PCI_BRIDGE_BAR_0 0
#define PCI_BRIDGE_BAR_1 1
#define PCI_BRIDGE_IO_WINDOW 2
#define PCI_BRIDGE_MEMORY_WINDOW 3
#define PCI_BRIDGE_PREFETCH_WINDOW 4
#define PCI_BRIDGE_BAR_ROM 5
#define PCI_CARDBUS_SOCKET_BAR 0
#define PCI_CARDBUS_MEMORY_WINDOW_0 1
#define PCI_CARDBUS_MEMORY_WINDOW_1 2
#define PCI_CARDBUS_IO_WINDOW_0 3
#define PCI_CARDBUS_IO_WINDOW_1 4
#define PCI_CARDBUS_LEGACY_BAR 5 // Not used
typedef struct {
ULONGLONG Total;
ULONG Alignment;
} PCI_RESOURCE_ACCUMULATOR, *PPCI_RESOURCE_ACCUMULATOR;
typedef struct {
SYSTEM_POWER_STATE CurrentSystemState;
DEVICE_POWER_STATE CurrentDeviceState;
SYSTEM_POWER_STATE SystemWakeLevel;
DEVICE_POWER_STATE DeviceWakeLevel;
DEVICE_POWER_STATE SystemStateMapping[PowerSystemMaximum];
PIRP WaitWakeIrp;
PDRIVER_CANCEL SavedCancelRoutine;
// device usage...
LONG Paging;
LONG Hibernate;
LONG CrashDump;
} PCI_POWER_STATE, *PPCI_POWER_STATE;
typedef struct _PCI_PDO_EXTENSION *PPCI_PDO_EXTENSION;
typedef struct _PCI_FDO_EXTENSION *PPCI_FDO_EXTENSION;
typedef struct _PCI_COMMON_EXTENSION *PPCI_COMMON_EXTENSION;
//
// This is an Irp Dispatch Handler for PCI
//
typedef NTSTATUS (*PCI_MN_DISPATCH_FUNCTION) (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
typedef struct _PCI_MN_DISPATCH_TABLE {
PCI_DISPATCH_STYLE DispatchStyle;
PCI_MN_DISPATCH_FUNCTION DispatchFunction;
} PCI_MN_DISPATCH_TABLE, *PPCI_MN_DISPATCH_TABLE;
//
// This is a table that contains everything neccessary to handle Power, PnP,
// and other IRPs.
//
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_MN_DISPATCH_FUNCTION SystemControlIrpDispatchFunction;
PCI_DISPATCH_STYLE OtherIrpDispatchStyle;
PCI_MN_DISPATCH_FUNCTION OtherIrpDispatchFunction;
} PCI_MJ_DISPATCH_TABLE, *PPCI_MJ_DISPATCH_TABLE;
typedef
VOID
(*PCRITICALROUTINE)(
IN PVOID Extension,
IN PVOID Context
);
typedef struct _PCI_CRITICAL_ROUTINE_CONTEXT {
volatile LONG Gate;
volatile LONG Barrier;
PCRITICALROUTINE Routine;
PVOID Extension;
PVOID Context;
} PCI_CRITICAL_ROUTINE_CONTEXT, *PPCI_CRITICAL_ROUTINE_CONTEXT;
//
// Structure used for storing MSI routing info
// in the PDO extention.
//
typedef struct _PCI_MSI_INFO {
ULONG_PTR MessageAddress;
UCHAR CapabilityOffset;
USHORT MessageData;
} PCI_MSI_INFO, *PPCI_MSI_INFO;
//
// This much must be common to both the PDO and FDO extensions.
//
typedef struct _PCI_COMMON_EXTENSION {
PVOID Next;
PCI_SIGNATURE ExtensionType;
PPCI_MJ_DISPATCH_TABLE IrpDispatchTable;
UCHAR DeviceState;
UCHAR TentativeNextState;
FAST_MUTEX SecondaryExtMutex;
} PCI_COMMON_EXTENSION;
typedef struct _PCI_PDO_EXTENSION{
PPCI_PDO_EXTENSION Next;
PCI_SIGNATURE ExtensionType;
PPCI_MJ_DISPATCH_TABLE IrpDispatchTable;
UCHAR DeviceState;
UCHAR TentativeNextState;
FAST_MUTEX SecondaryExtMutex;
PCI_SLOT_NUMBER Slot;
PDEVICE_OBJECT PhysicalDeviceObject;
PPCI_FDO_EXTENSION ParentFdoExtension;
SINGLE_LIST_ENTRY SecondaryExtension;
ULONG BusInterfaceReferenceCount;
ULONG AgpInterfaceReferenceCount;
USHORT VendorId;
USHORT DeviceId;
USHORT SubsystemVendorId;
USHORT SubsystemId;
UCHAR RevisionId;
UCHAR ProgIf;
UCHAR SubClass;
UCHAR BaseClass;
UCHAR AdditionalResourceCount;
UCHAR AdjustedInterruptLine;
UCHAR InterruptPin;
UCHAR RawInterruptLine;
UCHAR CapabilitiesPtr;
UCHAR SavedLatencyTimer;
UCHAR SavedCacheLineSize;
UCHAR HeaderType;
BOOLEAN NotPresent;
BOOLEAN ReportedMissing;
BOOLEAN ExpectedWritebackFailure;
BOOLEAN NoTouchPmeEnable;
BOOLEAN LegacyDriver;
BOOLEAN UpdateHardware;
BOOLEAN MovedDevice;
BOOLEAN DisablePowerDown;
BOOLEAN NeedsHotPlugConfiguration;
BOOLEAN IDEInNativeMode;
BOOLEAN BIOSAllowsIDESwitchToNativeMode; // NATA method said it was OK
BOOLEAN IoSpaceUnderNativeIdeControl;
BOOLEAN OnDebugPath; // Includes headless port
#if MSI_SUPPORTED
BOOLEAN CapableMSI;
PCI_MSI_INFO MsiInfo;
#endif // MSI_SUPPORTED
PCI_POWER_STATE PowerState;
PCI_HEADER_TYPE_DEPENDENT Dependent;
ULONGLONG HackFlags;
PPCI_FUNCTION_RESOURCES Resources;
PPCI_FDO_EXTENSION BridgeFdoExtension;
PPCI_PDO_EXTENSION NextBridge;
PPCI_PDO_EXTENSION NextHashEntry;
PCI_LOCK Lock;
PCI_PMC PowerCapabilities;
UCHAR TargetAgpCapabilityId;
USHORT CommandEnables; // What we want to enable for this device
USHORT InitialCommand; // How we found the command register
} PCI_PDO_EXTENSION;
#define ASSERT_PCI_PDO_EXTENSION(x) \
PCI_ASSERT((x)->ExtensionType == PciPdoExtensionType)
typedef struct _PCI_FDO_EXTENSION{
SINGLE_LIST_ENTRY List; // List of pci.sys's FDOs
PCI_SIGNATURE ExtensionType; // PciFdoExtensionType
PPCI_MJ_DISPATCH_TABLE IrpDispatchTable; // Irp Dispatch Table to use.
UCHAR DeviceState;
UCHAR TentativeNextState;
FAST_MUTEX SecondaryExtMutex;
PDEVICE_OBJECT PhysicalDeviceObject; // PDO passed into AddDevice()
PDEVICE_OBJECT FunctionalDeviceObject;// FDO that points here
PDEVICE_OBJECT AttachedDeviceObject; // next DO in chain.
FAST_MUTEX ChildListMutex;
PPCI_PDO_EXTENSION ChildPdoList;
PPCI_FDO_EXTENSION BusRootFdoExtension; // points to top of this tree
PPCI_FDO_EXTENSION ParentFdoExtension; // points to the parent bridge
PPCI_PDO_EXTENSION ChildBridgePdoList;
PPCI_BUS_INTERFACE_STANDARD PciBusInterface; // Only for a root
UCHAR MaxSubordinateBus; // Only for a root
PBUS_HANDLER BusHandler;
UCHAR BaseBus; // Bus number for THIS bus
BOOLEAN Fake; // True if not a real FDOx
BOOLEAN Scanned; // True is bus enumerated
BOOLEAN ArbitersInitialized;
BOOLEAN BrokenVideoHackApplied;
BOOLEAN Hibernated;
PCI_POWER_STATE PowerState;
SINGLE_LIST_ENTRY SecondaryExtension;
ULONG ChildWaitWakeCount;
#if INTEL_ICH_HACKS
PPCI_COMMON_CONFIG IchHackConfig;
#endif
PCI_LOCK Lock;
//
// Information from ACPI _HPP to apply to hot plugged cards,
// Acquired indicates the rest are valid.
//
struct {
BOOLEAN Acquired;
UCHAR CacheLineSize;
UCHAR LatencyTimer;
BOOLEAN EnablePERR;
BOOLEAN EnableSERR;
} HotPlugParameters;
ULONG BusHackFlags; // see PCI_BUS_HACK_*
} PCI_FDO_EXTENSION;
#define ASSERT_PCI_FDO_EXTENSION(x) \
PCI_ASSERT((x)->ExtensionType == PciFdoExtensionType)
typedef struct _PCI_CONFIGURABLE_OBJECT {
PPCI_PDO_EXTENSION PdoExtension;
PPCI_COMMON_CONFIG Current;
PPCI_COMMON_CONFIG Working;
PPCI_CONFIGURATOR Configurator;
ULONG PrivateData;
USHORT Status;
USHORT Command;
} PCI_CONFIGURABLE_OBJECT, *PPCI_CONFIGURABLE_OBJECT;
typedef struct _PCI_ASSIGNED_RESOURCE_EXTENSION {
ULONG ResourceIdentifier;
} PCI_ASSIGNED_RESOURCE_EXTENSION, *PPCI_ASSIGNED_RESOURCE_EXTENSION;
//
// The PCI_COMMON_CONFIG includes the 192 bytes of device specific
// data. The following structure is used to get only the first 64
// bytes which is all we care about most of the time anyway. We cast
// to PCI_COMMON_CONFIG to get at the actual fields.
//
typedef struct {
ULONG Reserved[PCI_COMMON_HDR_LENGTH/sizeof(ULONG)];
} PCI_COMMON_HEADER, *PPCI_COMMON_HEADER;
//
// In order to be able to arbitrate interrupts for device with
// legacy drivers, we have to do some bookkeeping.
//
typedef struct {
SINGLE_LIST_ENTRY List;
PDEVICE_OBJECT LegacyDeviceObject;
ULONG Bus;
ULONG PciSlot;
UCHAR InterruptLine;
UCHAR InterruptPin;
UCHAR ClassCode;
UCHAR SubClassCode;
PDEVICE_OBJECT ParentPdo;
ROUTING_TOKEN RoutingToken;
PPCI_PDO_EXTENSION PdoExtension;
} LEGACY_DEVICE, *PLEGACY_DEVICE;
extern PLEGACY_DEVICE PciLegacyDeviceHead;
#define PCI_HACK_FLAG_SUBSYSTEM 0x01
#define PCI_HACK_FLAG_REVISION 0x02
typedef struct _PCI_HACK_TABLE_ENTRY {
USHORT VendorID;
USHORT DeviceID;
USHORT SubVendorID;
USHORT SubSystemID;
ULONGLONG HackFlags;
UCHAR RevisionID;
UCHAR Flags;
} PCI_HACK_TABLE_ENTRY, *PPCI_HACK_TABLE_ENTRY;
typedef struct _ARBITER_MEMORY_EXTENSION {
//
// Indicates that this arbiter will arbitrate prefetchable memory
//
BOOLEAN PrefetchablePresent;
//
// Indicates that this arbiter has been initialized
//
BOOLEAN Initialized;
//
// The number of prefetchable ranges
//
USHORT PrefetchableCount;
//
// The allocation ordering list to be used for prefetchable memory
//
ARBITER_ORDERING_LIST PrefetchableOrdering;
//
// The allocation ordering list to be used for standard memory
//
ARBITER_ORDERING_LIST NonprefetchableOrdering;
//
// The original memory allocation ordering (from the registry)
//
ARBITER_ORDERING_LIST OriginalOrdering;
} ARBITER_MEMORY_EXTENSION, *PARBITER_MEMORY_EXTENSION;
NTSTATUS
PciCacheLegacyDeviceRouting(
IN PDEVICE_OBJECT LegacyDO,
IN ULONG Bus,
IN ULONG PciSlot,
IN UCHAR InterruptLine,
IN UCHAR InterruptPin,
IN UCHAR ClassCode,
IN UCHAR SubClassCode,
IN PDEVICE_OBJECT ParentPdo,
IN PPCI_PDO_EXTENSION PdoExtension,
OUT PDEVICE_OBJECT *OldLegacyDO
);
//
// Global data declarations follow
//
extern PDRIVER_OBJECT PciDriverObject;
extern UNICODE_STRING PciServiceRegistryPath;
extern SINGLE_LIST_ENTRY PciFdoExtensionListHead;
extern FAST_MUTEX PciGlobalLock;
extern FAST_MUTEX PciBusLock;
extern LONG PciRootBusCount;
extern BOOLEAN PciAssignBusNumbers;
extern PPCI_FDO_EXTENSION PciRootExtensions;
extern RTL_RANGE_LIST PciIsaBitExclusionList;
extern RTL_RANGE_LIST PciVgaAndIsaBitExclusionList;
extern ULONG PciSystemWideHackFlags;
extern ULONG PciEnableNativeModeATA;
extern PPCI_HACK_TABLE_ENTRY PciHackTable;
extern BOOLEAN PciRunningDatacenter;
//
// Watchdog timer resource table
//
extern PWATCHDOG_TIMER_RESOURCE_TABLE WdTable;
// arb_comn.h
#define INSTANCE_NAME_LENGTH 24
typedef struct _PCI_ARBITER_INSTANCE {
//
// Standard secondary extension header
//
PCI_SECONDARY_EXTENSION Header;
//
// Back pointer to the interface we are a context of
//
struct _PCI_INTERFACE *Interface;
//
// Pointer to owning device object (extension).
//
PPCI_FDO_EXTENSION BusFdoExtension;
//
// Arbiter description.
//
WCHAR InstanceName[INSTANCE_NAME_LENGTH];
//
// The common instance data
//
ARBITER_INSTANCE CommonInstance;
} PCI_ARBITER_INSTANCE, *PPCI_ARBITER_INSTANCE;
NTSTATUS
PciArbiterInitializeInterface(
IN PVOID DeviceExtension,
IN PCI_SIGNATURE DesiredInterface,
IN OUT PARBITER_INTERFACE ArbiterInterface
);
NTSTATUS
PciInitializeArbiterRanges(
IN PPCI_FDO_EXTENSION FdoExtension,
IN PCM_RESOURCE_LIST ResourceList
);
NTSTATUS
PciInitializeArbiters(
IN PVOID DeviceExtension
);
VOID
PciReferenceArbiter(
IN PVOID Context
);
VOID
PciDereferenceArbiter(
IN PVOID Context
);
VOID
ario_ApplyBrokenVideoHack(
IN PPCI_FDO_EXTENSION FdoExtension
);
// busno.h
BOOLEAN
PciAreBusNumbersConfigured(
IN PPCI_PDO_EXTENSION Bridge
);
VOID
PciConfigureBusNumbers(
PPCI_FDO_EXTENSION Parent
);
VOID
PciSetBusNumbers(
IN PPCI_PDO_EXTENSION PdoExtension,
IN UCHAR Primary,
IN UCHAR Secondary,
IN UCHAR Subordinate
);
// cardbus.h
VOID
Cardbus_MassageHeaderForLimitsDetermination(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Cardbus_RestoreCurrent(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Cardbus_SaveLimits(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Cardbus_SaveCurrentSettings(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Cardbus_ChangeResourceSettings(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
VOID
Cardbus_GetAdditionalResourceDescriptors(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig,
IN PIO_RESOURCE_DESCRIPTOR Resource
);
NTSTATUS
Cardbus_ResetDevice(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
// config.h
VOID
PciReadDeviceConfig(
IN PPCI_PDO_EXTENSION Pdo,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
VOID
PciWriteDeviceConfig(
IN PPCI_PDO_EXTENSION Pdo,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
VOID
PciReadSlotConfig(
IN PPCI_FDO_EXTENSION ParentFdo,
IN PCI_SLOT_NUMBER SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
VOID
PciWriteSlotConfig(
IN PPCI_FDO_EXTENSION ParentFdo,
IN PCI_SLOT_NUMBER SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
UCHAR
PciGetAdjustedInterruptLine(
IN PPCI_PDO_EXTENSION Pdo
);
NTSTATUS
PciExternalReadDeviceConfig(
IN PPCI_PDO_EXTENSION Pdo,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
NTSTATUS
PciExternalWriteDeviceConfig(
IN PPCI_PDO_EXTENSION Pdo,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
NTSTATUS
PciGetConfigHandlers(
IN PPCI_FDO_EXTENSION FdoExtension
);
//
// Macros to access common registers in config space
//
//
// VOID
// PciGetCommandRegister(
// PPCI_PDO_EXTENSION _PdoExt,
// PUSHORT _Command
// );
//
#define PciGetCommandRegister(_PdoExt, _Command) \
PciReadDeviceConfig((_PdoExt), \
(_Command), \
FIELD_OFFSET(PCI_COMMON_CONFIG, Command), \
sizeof(USHORT) \
);
//
// VOID
// PciSetCommandRegister(
// PPCI_PDO_EXTENSION _PdoExt,
// USHORT _Command
// );
//
#define PciSetCommandRegister(_PdoExt, _Command) \
PciWriteDeviceConfig((_PdoExt), \
&(_Command), \
FIELD_OFFSET(PCI_COMMON_CONFIG, Command), \
sizeof(USHORT) \
);
// BOOLEAN
// BITS_SET(
// IN USHORT C
// IN USHORT F
// )
//
#define BITS_SET(C,F) ((BOOLEAN)(((C) & (F)) == (F)))
// BOOLEAN
// ANY_BITS_SET(
// IN USHORT C
// IN USHORT F
// )
//
#define ANY_BITS_SET(C,F) ((BOOLEAN)(((C) & (F)) != 0))
//
// VOID
// PciGetConfigData(
// IN PPCI_PDO_EXTENSION PdoExtension,
// OUT PPCI_COMMON_CONFIG PciConfig
// )
//
#define PciGetConfigData(_PdoExtension, _PciConfig) \
PciReadDeviceConfig((_PdoExtension), \
(_PciConfig), \
0, \
PCI_COMMON_HDR_LENGTH \
);
//
// VOID
// PciSetConfigData(
// IN PPCI_PDO_EXTENSION PdoExtension,
// OUT PPCI_COMMON_CONFIG PciConfig
// )
//
#define PciSetConfigData(_PdoExtension, _PciConfig) \
PciWriteDeviceConfig((_PdoExtension), \
(_PciConfig), \
0, \
PCI_COMMON_HDR_LENGTH \
);
// debug.c
typedef enum {
PciDbgAlways = 0x00000000, // unconditionally
PciDbgInformative = 0x00000001,
PciDbgVerbose = 0x00000003,
PciDbgPrattling = 0x00000007,
PciDbgPnpIrpsFdo = 0x00000100, // PnP IRPs at FDO
PciDbgPnpIrpsPdo = 0x00000200, // PnP IRPs at PDO
PciDbgPoIrpsFdo = 0x00000400, // PO IRPs at FDO
PciDbgPoIrpsPdo = 0x00000800, // PO IRPs at PDO
PciDbgAddDevice = 0x00001000, // AddDevice info
PciDbgAddDeviceRes = 0x00002000, // bus initial resource info
PciDbgWaitWake = 0x00008000, // noisy debug for wait wake
PciDbgQueryCap = 0x00010000, // Dump QueryCapabilities
PciDbgCardBus = 0x00020000, // CardBus FDOish behavior
PciDbgROM = 0x00040000, // access to device ROM
PciDbgConfigParam = 0x00080000, // Setting config parameters
PciDbgBusNumbers = 0x00100000, // checking and assigning bus numbers
PciDbgResReqList = 0x01000000, // generated resource requirements
PciDbgCmResList = 0x02000000, // generated CM Resource lists
PciDbgSetResChange = 0x04000000, // SetResources iff changing
PciDbgSetRes = 0x08000000, // SetResources
PciDbgObnoxious = 0x7fffffff // anything
} PCI_DEBUG_LEVEL;
#if DBG
#define PCI_DEBUGGING_OKAY() \
(KeGetCurrentIrql() < IPI_LEVEL)
#define PCI_ASSERT \
if (PCI_DEBUGGING_OKAY()) ASSERT
#define PCI_ASSERTMSG \
if (PCI_DEBUGGING_OKAY()) ASSERTMSG
extern PCI_DEBUG_LEVEL PciDebug;
#define PCI_DEBUG_BUFFER_SIZE 256
#define PciDebugPrint PciDebugPrintIfLevel
#else
#define PciDebugPrint if(0)
#define PCI_ASSERT(exp)
#define PCI_ASSERTMSG(msg,exp)
#endif
VOID
PciDebugDumpCommonConfig(
IN PPCI_COMMON_CONFIG CommonConfig
);
VOID
PciDebugDumpQueryCapabilities(
IN PDEVICE_CAPABILITIES C
);
VOID
PciDebugHit(
ULONG StopOnBit
);
PUCHAR
PciDebugPnpIrpTypeToText(
ULONG IrpMinorCode
);
PUCHAR
PciDebugPoIrpTypeToText(
ULONG IrpMinorCode
);
VOID
PciDebugPrintIfLevel(
PCI_DEBUG_LEVEL DebugPrintLevel,
PCCHAR DebugMessage,
...
);
VOID
PciDebugPrintf(
PCCHAR DebugMessage,
...
);
VOID
PciDebugPrintCmResList(
PCI_DEBUG_LEVEL DebugPrintLevel,
IN PCM_RESOURCE_LIST ResourceList
);
VOID
PciDebugPrintIoResource(
IN PIO_RESOURCE_DESCRIPTOR Descriptor
);
VOID
PciDebugPrintIoResReqList(
IN PIO_RESOURCE_REQUIREMENTS_LIST List
);
VOID
PciDebugPrintPartialResource(
PCI_DEBUG_LEVEL DebugPrintLevel,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR D
);
// device.h
VOID
Device_MassageHeaderForLimitsDetermination(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Device_RestoreCurrent(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Device_SaveLimits(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Device_SaveCurrentSettings(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
Device_ChangeResourceSettings(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
VOID
Device_GetAdditionalResourceDescriptors(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig,
IN PIO_RESOURCE_DESCRIPTOR Resource
);
NTSTATUS
Device_ResetDevice(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
// dispatch.h
//
// This is the dispatch table for normal PDO's.
//
extern PCI_MJ_DISPATCH_TABLE PciPdoDispatchTable;
NTSTATUS
PciDispatchIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
PciPassIrpFromFdoToPdo(
PPCI_COMMON_EXTENSION DeviceExtension,
PIRP Irp
);
NTSTATUS
PciCallDownIrpStack(
PPCI_COMMON_EXTENSION DeviceExtension,
PIRP Irp
);
NTSTATUS
PciIrpNotSupported(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciIrpInvalidDeviceRequest(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
// enum.h
PIO_RESOURCE_REQUIREMENTS_LIST
PciAllocateIoRequirementsList(
IN ULONG ResourceCount,
IN ULONG BusNumber,
IN ULONG SlotNumber
);
BOOLEAN
PciComputeNewCurrentSettings(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PCM_RESOURCE_LIST ResourceList
);
NTSTATUS
PciQueryDeviceRelations(
IN PPCI_FDO_EXTENSION FdoExtension,
OUT PDEVICE_RELATIONS *DeviceRelations
);
NTSTATUS
PciQueryRequirements(
IN PPCI_PDO_EXTENSION PdoExtension,
OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementsList
);
NTSTATUS
PciQueryResources(
IN PPCI_PDO_EXTENSION PdoExtension,
OUT PCM_RESOURCE_LIST *ResourceList
);
NTSTATUS
PciQueryTargetDeviceRelations(
IN PPCI_PDO_EXTENSION PdoExtension,
IN OUT PDEVICE_RELATIONS *PDeviceRelations
);
NTSTATUS
PciQueryEjectionRelations(
IN PPCI_PDO_EXTENSION PdoExtension,
IN OUT PDEVICE_RELATIONS *PDeviceRelations
);
NTSTATUS
PciScanHibernatedBus(
IN PPCI_FDO_EXTENSION FdoExtension
);
NTSTATUS
PciSetResources(
IN PPCI_PDO_EXTENSION PdoExtension,
IN BOOLEAN PowerOn,
IN BOOLEAN StartDeviceIrp
);
VOID
PciUpdateHardware(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG Config
);
BOOLEAN
PciIsSameDevice(
IN PPCI_PDO_EXTENSION PdoExtension
);
NTSTATUS
PciBuildRequirementsList(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CurrentConfig,
OUT PIO_RESOURCE_REQUIREMENTS_LIST *FinalReqList
);
// fdo.h
NTSTATUS
PciFdoIrpQueryDeviceRelations(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
);
VOID
PciInitializeFdoExtensionCommonFields(
IN PPCI_FDO_EXTENSION FdoExtension,
IN PDEVICE_OBJECT Fdo,
IN PDEVICE_OBJECT Pdo
);
// hookhal.c
VOID
PciHookHal(
VOID
);
VOID
PciUnhookHal(
VOID
);
// id.h
PWSTR
PciGetDeviceDescriptionMessage(
IN UCHAR BaseClass,
IN UCHAR SubClass
);
NTSTATUS
PciQueryId(
IN PPCI_PDO_EXTENSION PdoExtension,
IN BUS_QUERY_ID_TYPE IdType,
IN OUT PWSTR *BusQueryId
);
NTSTATUS
PciQueryDeviceText(
IN PPCI_PDO_EXTENSION PdoExtension,
IN DEVICE_TEXT_TYPE TextType,
IN LCID LocaleId,
IN OUT PWSTR *DeviceText
);
// interface.h
#define PCIIF_PDO 0x01 // Interface can be used by a PDO
#define PCIIF_FDO 0x02 // Interface can be used by an FDO
#define PCIIF_ROOT 0x04 // Interface can be used only at by the root.
typedef
NTSTATUS
(*PPCI_INTERFACE_CONSTRUCTOR)(
PVOID DeviceExtension,
PVOID PciInterface,
PVOID InterfaceSpecificData,
USHORT Version,
USHORT Size,
PINTERFACE InterfaceReturn
);
typedef
NTSTATUS
(*PPCI_INTERFACE_INITIALIZER)(
PPCI_ARBITER_INSTANCE Instance
);
typedef struct _PCI_INTERFACE {
PGUID InterfaceType;
USHORT MinSize;
USHORT MinVersion;
USHORT MaxVersion;
USHORT Flags;
LONG ReferenceCount;
PCI_SIGNATURE Signature;
PPCI_INTERFACE_CONSTRUCTOR Constructor;
PPCI_INTERFACE_INITIALIZER Initializer;
} PCI_INTERFACE, *PPCI_INTERFACE;
NTSTATUS
PciQueryInterface(
IN PVOID DeviceExtension,
IN PGUID InterfaceType,
IN USHORT Size,
IN USHORT Version,
IN PVOID InterfaceSpecificData,
IN OUT PINTERFACE Interface,
IN BOOLEAN LastChance
);
extern PPCI_INTERFACE PciInterfaces[];
// pdo.h
NTSTATUS
PciPdoCreate(
IN PPCI_FDO_EXTENSION FdoExtension,
IN PCI_SLOT_NUMBER Slot,
OUT PDEVICE_OBJECT *PhysicalDeviceObject
);
VOID
PciPdoDestroy(
IN PDEVICE_OBJECT PhysicalDeviceObject
);
// pmeintf.h
VOID
PciPmeAdjustPmeEnable(
IN PPCI_PDO_EXTENSION PdoExtension,
IN BOOLEAN Enable,
IN BOOLEAN ClearStatusOnly
);
VOID
PciPmeGetInformation(
IN PDEVICE_OBJECT Pdo,
OUT PBOOLEAN PmeCapable,
OUT PBOOLEAN PmeStatus,
OUT PBOOLEAN PmeEnable
);
// power.h
NTSTATUS
PciPdoIrpQueryPower(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciPdoSetPowerState (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciPdoWaitWake (
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
VOID
PciPdoWaitWakeCancelRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PciFdoIrpQueryPower(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciFdoSetPowerState(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciFdoWaitWake(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp,
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciSetPowerManagedDevicePowerState(
IN PPCI_PDO_EXTENSION PdoExtension,
IN DEVICE_POWER_STATE DeviceState,
IN BOOLEAN RefreshConfigSpace
);
// ppbridge.h
VOID
PPBridge_MassageHeaderForLimitsDetermination(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
PPBridge_RestoreCurrent(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
PPBridge_SaveLimits(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
PPBridge_SaveCurrentSettings(
IN PPCI_CONFIGURABLE_OBJECT This
);
VOID
PPBridge_ChangeResourceSettings(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
VOID
PPBridge_GetAdditionalResourceDescriptors(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig,
IN PIO_RESOURCE_DESCRIPTOR Resource
);
NTSTATUS
PPBridge_ResetDevice(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG CommonConfig
);
// romimage.h
NTSTATUS
PciReadRomImage(
IN PPCI_PDO_EXTENSION PdoExtension,
IN ULONG WhichSpace,
OUT PVOID Buffer,
IN ULONG Offset,
IN OUT PULONG LENGTH
);
// state.h
//
// Note - State.c depends on the order of these.
//
typedef enum {
PciNotStarted = 0,
PciStarted,
PciDeleted,
PciStopped,
PciSurpriseRemoved,
PciSynchronizedOperation,
PciMaxObjectState
} PCI_OBJECT_STATE;
VOID
PciInitializeState(
IN PPCI_COMMON_EXTENSION DeviceExtension
);
NTSTATUS
PciBeginStateTransition(
IN PPCI_COMMON_EXTENSION DeviceExtension,
IN PCI_OBJECT_STATE NewState
);
VOID
PciCommitStateTransition(
IN PPCI_COMMON_EXTENSION DeviceExtension,
IN PCI_OBJECT_STATE NewState
);
NTSTATUS
PciCancelStateTransition(
IN PPCI_COMMON_EXTENSION DeviceExtension,
IN PCI_OBJECT_STATE StateNotEntered
);
BOOLEAN
PciIsInTransitionToState(
IN PPCI_COMMON_EXTENSION DeviceExtension,
IN PCI_OBJECT_STATE NextState
);
/*
NTSTATUS
PciBeginStateTransitionIfNotBegun(
IN PPCI_COMMON_EXTENSION DeviceExtension,
IN PCI_OBJECT_STATE StateToEnter
);
*/
#define PCI_ACQUIRE_STATE_LOCK(Extension) \
PciBeginStateTransition((PPCI_COMMON_EXTENSION) (Extension), \
PciSynchronizedOperation)
#define PCI_RELEASE_STATE_LOCK(Extension) \
PciCancelStateTransition((PPCI_COMMON_EXTENSION) (Extension), \
PciSynchronizedOperation)
// tr_comn.h
typedef struct _PCI_TRANSLATOR_INSTANCE {
PTRANSLATOR_INTERFACE Interface;
ULONG ReferenceCount;
PPCI_FDO_EXTENSION FdoExtension;
} PCI_TRANSLATOR_INSTANCE, *PPCI_TRANSLATOR_INSTANCE;
#define PCI_TRANSLATOR_INSTANCE_TO_CONTEXT(x) ((PVOID)(x))
#define PCI_TRANSLATOR_CONTEXT_TO_INSTANCE(x) ((PPCI_TRANSLATOR_INSTANCE)(x))
VOID
PciReferenceTranslator(
IN PVOID Context
);
VOID
PciDereferenceTranslator(
IN PVOID Context
);
// usage.h
NTSTATUS
PciLocalDeviceUsage (
IN PPCI_POWER_STATE PowerState,
IN PIRP Irp
);
NTSTATUS
PciPdoDeviceUsage (
IN PPCI_PDO_EXTENSION pdoExtension,
IN PIRP Irp
);
// utils.h
NTSTATUS
PciAssignSlotResources(
IN PUNICODE_STRING RegistryPath,
IN PUNICODE_STRING DriverClassName OPTIONAL,
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN INTERFACE_TYPE BusType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN OUT PCM_RESOURCE_LIST *AllocatedResources
);
PCI_OBJECT_TYPE
PciClassifyDeviceType(
PPCI_PDO_EXTENSION PdoExtension
);
// VOID
// PciCompleteRequest(
// IN OUT PIRP Irp,
// IN NTSTATUS Status
// );
#define PciCompleteRequest(_Irp_,_Status_) \
{ \
(_Irp_)->IoStatus.Status = (_Status_); \
IoCompleteRequest((_Irp_), IO_NO_INCREMENT); \
}
BOOLEAN
PciCreateIoDescriptorFromBarLimit(
IN PIO_RESOURCE_DESCRIPTOR Descriptor,
IN PULONG BaseAddress,
IN BOOLEAN Rom
);
BOOLEAN
PciIsCriticalDeviceClass(
IN UCHAR BaseClass,
IN UCHAR SubClass
);
#define PCI_CAN_DISABLE_VIDEO_DECODES 0x00000001
BOOLEAN
PciCanDisableDecodes(
IN PPCI_PDO_EXTENSION PdoExtension OPTIONAL,
IN PPCI_COMMON_CONFIG Config OPTIONAL,
IN ULONGLONG HackFlags,
IN ULONG Flags
);
VOID
PciDecodeEnable(
IN PPCI_PDO_EXTENSION PdoExtension,
IN BOOLEAN EnableOperation,
IN PUSHORT ExistingCommand OPTIONAL
);
PCM_PARTIAL_RESOURCE_DESCRIPTOR
PciFindDescriptorInCmResourceList(
IN CM_RESOURCE_TYPE DescriptorType,
IN PCM_RESOURCE_LIST ResourceList,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR PreviousHit
);
PPCI_FDO_EXTENSION
PciFindParentPciFdoExtension(
PDEVICE_OBJECT PhysicalDeviceObject,
IN PFAST_MUTEX Mutex
);
PPCI_PDO_EXTENSION
PciFindPdoByFunction(
IN PPCI_FDO_EXTENSION FdoExtension,
IN PCI_SLOT_NUMBER Slot,
IN PPCI_COMMON_CONFIG Config
);
PVOID
PciFindNextSecondaryExtension(
IN PSINGLE_LIST_ENTRY ListEntry,
IN PCI_SIGNATURE DesiredType
);
#define PciFindSecondaryExtension(X,TYPE) \
PciFindNextSecondaryExtension((X)->SecondaryExtension.Next, TYPE)
VOID
PcipLinkSecondaryExtension(
IN PSINGLE_LIST_ENTRY ListHead,
IN PFAST_MUTEX Mutex,
IN PVOID NewExtension,
IN PCI_SIGNATURE Type,
IN PSECONDARYEXTENSIONDESTRUCTOR Destructor
);
#define PciLinkSecondaryExtension(X,X2,T,D) \
PcipLinkSecondaryExtension(&(X)->SecondaryExtension, \
&(X)->SecondaryExtMutex, \
X2, \
T, \
D)
VOID
PcipDestroySecondaryExtension(
IN PSINGLE_LIST_ENTRY ListHead,
IN PFAST_MUTEX Mutex,
IN PVOID Extension
);
ULONGLONG
PciGetHackFlags(
IN USHORT VendorID,
IN USHORT DeviceID,
IN USHORT SubVendorID,
IN USHORT SubSystemID,
IN UCHAR RevisionID
);
NTSTATUS
PciGetDeviceProperty(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
OUT PVOID *PropertyBuffer
);
NTSTATUS
PciGetInterruptAssignment(
IN PPCI_PDO_EXTENSION PdoExtension,
OUT ULONG *Minimum,
OUT ULONG *Maximum
);
ULONG
PciGetLengthFromBar(
ULONG BaseAddressRegister
);
NTSTATUS
PciGetRegistryValue(
IN PWSTR ValueName,
IN PWSTR KeyName,
IN HANDLE ParentHandle,
IN ULONG Type,
OUT PVOID *Buffer,
OUT PULONG Length
);
VOID
PciInsertEntryAtTail(
IN PSINGLE_LIST_ENTRY ListHead,
IN PSINGLE_LIST_ENTRY NewEntry,
IN PFAST_MUTEX Mutex
);
VOID
PciInsertEntryAtHead(
IN PSINGLE_LIST_ENTRY ListHead,
IN PSINGLE_LIST_ENTRY NewEntry,
IN PFAST_MUTEX Mutex
);
PCM_PARTIAL_RESOURCE_DESCRIPTOR
PciNextPartialDescriptor(
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
);
BOOLEAN
PciOpenKey(
IN PWSTR KeyName,
IN HANDLE ParentHandle,
IN ACCESS_MASK Access,
OUT PHANDLE ChildHandle,
OUT PNTSTATUS Status
);
NTSTATUS
PciQueryBusInformation(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPNP_BUS_INFORMATION *BusInformation
);
NTSTATUS
PciQueryLegacyBusInformation(
IN PPCI_FDO_EXTENSION FdoExtension,
IN PLEGACY_BUS_INFORMATION *BusInformation
);
NTSTATUS
PciQueryCapabilities(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PDEVICE_CAPABILITIES Capabilities
);
NTSTATUS
PciRangeListFromResourceList(
IN PPCI_FDO_EXTENSION FdoExtension,
IN PCM_RESOURCE_LIST ResourceList,
IN CM_RESOURCE_TYPE DesiredType,
IN BOOLEAN Complement,
IN PRTL_RANGE_LIST ResultRange
);
UCHAR
PciReadDeviceCapability(
IN PPCI_PDO_EXTENSION PdoExtension,
IN UCHAR Offset,
IN UCHAR Id,
IN OUT PVOID Buffer,
IN ULONG Length
);
VOID
PciRemoveEntryFromList(
IN PSINGLE_LIST_ENTRY ListHead,
IN PSINGLE_LIST_ENTRY OldEntry,
IN PFAST_MUTEX Mutex
);
PPCI_PDO_EXTENSION
PciFindPdoByLocation(
IN ULONG BusNumber,
IN PCI_SLOT_NUMBER Slot
);
NTSTATUS
PciBuildDefaultExclusionLists(
VOID
);
NTSTATUS
PciExcludeRangesFromWindow(
IN ULONGLONG Start,
IN ULONGLONG End,
IN PRTL_RANGE_LIST ArbiterRanges,
IN PRTL_RANGE_LIST ExclusionRanges
);
NTSTATUS
PciSaveBiosConfig(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG Config
);
NTSTATUS
PciGetBiosConfig(
IN PPCI_PDO_EXTENSION PdoExtension,
IN PPCI_COMMON_CONFIG Config
);
BOOLEAN
PciStringToUSHORT(
IN PWCHAR String,
OUT PUSHORT Result
);
NTSTATUS
PciSendIoctl(
IN PDEVICE_OBJECT Device,
IN ULONG IoctlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
IN PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
);
BOOLEAN
PciIsOnVGAPath(
IN PPCI_PDO_EXTENSION Pdo
);
BOOLEAN
PciIsSlotPresentInParentMethod(
IN PPCI_PDO_EXTENSION Pdo,
IN ULONG Method
);
NTSTATUS
PciUpdateLegacyHardwareDescription(
IN PPCI_FDO_EXTENSION Fdo
);
NTSTATUS
PciWriteDeviceSpace(
IN PPCI_PDO_EXTENSION PdoExtension,
IN ULONG WhichSpace,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length,
OUT PULONG LengthWritten
);
NTSTATUS
PciReadDeviceSpace(
IN PPCI_PDO_EXTENSION PdoExtension,
IN ULONG WhichSpace,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length,
OUT PULONG LengthRead
);
BOOLEAN
PciIsSuiteVersion(
IN USHORT Version
);
BOOLEAN
PciIsDatacenter(
);
ULONG_PTR
PciExecuteCriticalSystemRoutine(
IN ULONG_PTR Context
);
BOOLEAN
PciUnicodeStringStrStr(
IN PUNICODE_STRING SearchString,
IN PUNICODE_STRING SubString,
IN BOOLEAN CaseInsensitive
);
//
// Programming Interface encodings for PCI IDE Controllers
// BaseClass = 1, SubClass = 1
//
#define PCI_IDE_PRIMARY_NATIVE_MODE 0x01
#define PCI_IDE_PRIMARY_MODE_CHANGEABLE 0x02
#define PCI_IDE_SECONDARY_NATIVE_MODE 0x04
#define PCI_IDE_SECONDARY_MODE_CHANGEABLE 0x08
#define PCI_IS_LEGACY_IDE_CONTROLLER(_Config) \
((_Config)->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR \
&& (_Config)->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR \
&& !BITS_SET((_Config)->ProgIf, (PCI_IDE_PRIMARY_NATIVE_MODE \
| PCI_IDE_SECONDARY_NATIVE_MODE)))
#define PCI_IS_NATIVE_IDE_CONTROLLER(_Config) \
((_Config)->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR \
&& (_Config)->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR \
&& BITS_SET((_Config)->ProgIf, (PCI_IDE_PRIMARY_NATIVE_MODE \
| PCI_IDE_SECONDARY_NATIVE_MODE)))
#define PCI_IS_NATIVE_CAPABLE_IDE_CONTROLLER(_Config) \
((_Config)->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR \
&& (_Config)->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR \
&& BITS_SET((_Config)->ProgIf, (PCI_IDE_PRIMARY_MODE_CHANGEABLE \
| PCI_IDE_SECONDARY_MODE_CHANGEABLE)))
//
// _HPP method for HotPlugParameters
//
// Method (_HPP, 0) {
// Return (Package(){
// 0x00000008, // CacheLineSize in DWORDS
// 0x00000040, // LatencyTimer in PCI clocks
// 0x00000001, // Enable SERR (Boolean)
// 0x00000001 // Enable PERR (Boolean)
// })
//
#define PCI_HPP_CACHE_LINE_SIZE_INDEX 0
#define PCI_HPP_LATENCY_TIMER_INDEX 1
#define PCI_HPP_ENABLE_SERR_INDEX 2
#define PCI_HPP_ENABLE_PERR_INDEX 3
#define PCI_HPP_PACKAGE_COUNT 4
//
// Support for kernel debugger and headless ports that can't be turned off
// This is retrieved from the registry in DriverEntry and thus the bus numbers
// are how the firmware configured the machine and not necessarily the current
// settings. Luckily we saved away the BIOS config in the registry.
//
typedef struct _PCI_DEBUG_PORT {
ULONG Bus;
PCI_SLOT_NUMBER Slot;
} PCI_DEBUG_PORT, *PPCI_DEBUG_PORT;
extern PCI_DEBUG_PORT PciDebugPorts[];
extern ULONG PciDebugPortsCount;
BOOLEAN
PciIsDeviceOnDebugPath(
IN PPCI_PDO_EXTENSION Pdo
);
//
// Cardbus has extra configuration information beyond the common
// header.
//
typedef struct _TYPE2EXTRAS {
USHORT SubVendorID;
USHORT SubSystemID;
ULONG LegacyModeBaseAddress;
} TYPE2EXTRAS;
#define CARDBUS_LMBA_OFFSET \
(ULONG)(FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceSpecific) + \
FIELD_OFFSET(TYPE2EXTRAS, LegacyModeBaseAddress))
//
// Hack flags for PCI devices (PDO)
//
#define PCI_HACK_NO_VIDEO_IRQ 0x0000000000000001L
#define PCI_HACK_PCMCIA_WANT_IRQ 0x0000000000000002L
#define PCI_HACK_DUAL_IDE 0x0000000000000004L
#define PCI_HACK_NO_ENUM_AT_ALL 0x0000000000000008L
#define PCI_HACK_ENUM_NO_RESOURCE 0x0000000000000010L
#define PCI_HACK_NEED_DWORD_ACCESS 0x0000000000000020L
#define PCI_HACK_SINGLE_FUNCTION 0x0000000000000040L
#define PCI_HACK_ALWAYS_ENABLED 0x0000000000000080L
#define PCI_HACK_IS_IDE 0x0000000000000100L
#define PCI_HACK_IS_VIDEO 0x0000000000000200L
#define PCI_HACK_FAIL_START 0x0000000000000400L
#define PCI_HACK_GHOST 0x0000000000000800L
#define PCI_HACK_DOUBLE_DECKER 0x0000000000001000L
#define PCI_HACK_ONE_CHILD 0x0000000000002000L
#define PCI_HACK_PRESERVE_COMMAND 0x0000000000004000L
#define PCI_HACK_IS_VGA 0x0000000000008000L
#define PCI_HACK_CB_SHARE_CMD_BITS 0x0000000000010000L
#define PCI_HACK_STRAIGHT_IRQ_ROUTING 0x0000000000020000L
#define PCI_HACK_SUBTRACTIVE_DECODE 0x0000000000040000L
#define PCI_HACK_FDMA_ISA 0x0000000000080000L
#define PCI_HACK_EXCLUSIVE 0x0000000000100000L
#define PCI_HACK_EDGE 0x0000000000200000L
#define PCI_HACK_NO_SUBSYSTEM 0x0000000000400000L
#define PCI_HACK_NO_WPE 0x0000000000800000L
#define PCI_HACK_OLD_ID 0x0000000001000000L
#define PCI_HACK_DONT_SHRINK_BRIDGE 0x0000000002000000L
#define PCI_HACK_TURN_OFF_PARITY 0x0000000004000000L
#define PCI_HACK_NO_NON_PCI_CHILD_BAR 0x0000000008000000L
#define PCI_HACK_NO_ENUM_WITH_DISABLE 0x0000000010000000L
#define PCI_HACK_NO_PM_CAPS 0x0000000020000000L
#define PCI_HACK_NO_DISABLE_DECODES 0x0000000040000000L
#define PCI_HACK_NO_SUBSYSTEM_AFTER_D3 0x0000000080000000L
#define PCI_HACK_VIDEO_LEGACY_DECODE 0x0000000100000000L
#define PCI_HACK_FAKE_CLASS_CODE 0x0000000200000000L
#define PCI_HACK_RESET_BRIDGE_ON_POWERUP 0x0000000400000000L
#define PCI_HACK_BAD_NATIVE_IDE 0x0000000800000000L
#define PCI_HACK_FAIL_QUERY_REMOVE 0x0000001000000000L
#define PCI_HACK_CRITICAL_DEVICE 0x0000002000000000L
#define PCI_HACK_OVERRIDE_CRITICAL_DEVICE 0x0000004000000000L
//
// Hack flags for PCI busses (FDO)
// NB: These are not currently applied to cardbus bridges
//
//
// PCI_BUS_HACK_LOCK_RESOURCES - prevent devices on *this* bus from
// being moved. If a BAR are unconfigured it will still be assigned
// resources from what is available on the bus. If the BAR is
// configured only those resources if available will be assigned, if
// not available the the device will fail CM_PROBLEM_RESOURCE_CONFLICT.
//
// Putting /PCILOCK in boot.ini applies this to all devices in the system.
//
#define PCI_BUS_HACK_LOCK_RESOURCES 0x00000001
//
// Random useful macros
//
#ifndef FIELD_SIZE
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
#endif
//
// This macro computes if a range of bytes with configuration
// space from offset for length bytes will intersect with the
// any of the fields between field1 and field2 as defined in
// PCI_COMMON_CONFIG
//
#define INTERSECT_CONFIG_FIELD_RANGE(offset, length, field1, field2) \
INTERSECT((offset), \
(offset) + (length) - 1, \
FIELD_OFFSET(PCI_COMMON_CONFIG, field1), \
FIELD_OFFSET(PCI_COMMON_CONFIG, field2) \
+ FIELD_SIZE(PCI_COMMON_CONFIG, field2) - 1 \
)
//
// This macro computes if a range of bytes with configuration
// space from offset for length bytes will intersect with
// field as defined in PCI_COMMON_CONFIG
//
#define INTERSECT_CONFIG_FIELD(offset, length, field) \
INTERSECT_CONFIG_FIELD_RANGE(offset, length, field, field)
#endif