summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/extender/pci
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/extender/pci
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/extender/pci')
-rw-r--r--private/ntos/nthals/extender/pci/bus.c670
-rw-r--r--private/ntos/nthals/extender/pci/control.c662
-rw-r--r--private/ntos/nthals/extender/pci/devres.c1139
-rw-r--r--private/ntos/nthals/extender/pci/init.c357
-rw-r--r--private/ntos/nthals/extender/pci/makefile6
-rw-r--r--private/ntos/nthals/extender/pci/misc.c544
-rw-r--r--private/ntos/nthals/extender/pci/pcidata.c123
-rw-r--r--private/ntos/nthals/extender/pci/pciport.h570
-rw-r--r--private/ntos/nthals/extender/pci/pciport.rc11
-rw-r--r--private/ntos/nthals/extender/pci/port.c713
-rw-r--r--private/ntos/nthals/extender/pci/sources48
11 files changed, 4843 insertions, 0 deletions
diff --git a/private/ntos/nthals/extender/pci/bus.c b/private/ntos/nthals/extender/pci/bus.c
new file mode 100644
index 000000000..bd6e3aaf5
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/bus.c
@@ -0,0 +1,670 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ bus.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipCheckBus)
+#pragma alloc_text(PAGE,PciCtlCheckDevice)
+#pragma alloc_text(PAGE,PcipCrackBAR)
+#pragma alloc_text(PAGE,PcipVerifyBarBits)
+#pragma alloc_text(PAGE,PcipGetBarBits)
+#pragma alloc_text(PAGE,PcipFindDeviceData)
+#endif
+
+
+VOID
+PcipCheckBus (
+ PPCI_PORT PciPort,
+ BOOLEAN Initialize
+ )
+{
+ NTSTATUS Status;
+ PBUS_HANDLER Handler;
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG Device, Function;
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ BOOLEAN BusCheck, SkipDevice;
+ PDEVICE_DATA DeviceData;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ ULONG ObjectSize;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE Handle;
+ PSINGLE_LIST_ENTRY *Link;
+ BOOLEAN State;
+ POWER_STATE PowerState;
+ ULONG BufferSize;
+
+ PAGED_CODE();
+
+ Handler = PciPort->Handler;
+ BusCheck = FALSE;
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ //
+ // We may be removing references to this bus handler, so add
+ // a reference now
+ //
+
+ HalReferenceBusHandler (Handler);
+
+ //
+ // Check for any obslete device data entries
+ //
+
+ ExAcquireFastMutex (&PcipMutex);
+
+ Link = &PciPort->ValidSlots.Next;
+ while (*Link) {
+ DeviceData = CONTAINING_RECORD (*Link, DEVICE_DATA, Next);
+ if (!DeviceData->Valid) {
+
+ //
+ // Remove it from the list
+ //
+
+ *Link = (*Link)->Next;
+ BusCheck = TRUE;
+ PciPort->NoValidSlots -= 1;
+ HalDereferenceBusHandler (Handler);
+
+ //
+ // Dereference each obsolete device handler object once. This
+ // counters the original reference made to the device handler
+ // object when the object was created by this driver.
+ //
+
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+ ObDereferenceObject (DeviceHandler);
+ continue;
+ }
+
+ Link = & ((*Link)->Next);
+ }
+
+ ExReleaseFastMutex (&PcipMutex);
+
+
+ //
+ // Check the bus for new devices
+ //
+
+ SlotNumber.u.AsULONG = 0;
+ for (Device=0; Device < PCI_MAX_DEVICES; Device++) {
+ SlotNumber.u.bits.DeviceNumber = Device;
+ for (Function=0; Function < PCI_MAX_FUNCTION; Function++) {
+ SlotNumber.u.bits.FunctionNumber = Function;
+
+ //
+ // Read in the device id
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If not valid, skip it
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0) {
+ break;
+ }
+
+ //
+ // Check to see if this known configuration type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case PCI_DEVICE_TYPE:
+ case PCI_BRIDGE_TYPE:
+ SkipDevice = FALSE;
+ break;
+ default:
+ SkipDevice = TRUE;
+ break;
+ }
+
+ if (SkipDevice) {
+ break;
+ }
+
+ ExAcquireFastMutex (&PcipMutex);
+ DeviceData = PcipFindDeviceData (PciPort, SlotNumber);
+
+ if (DeviceData == NULL) {
+
+ //
+ // Initialize the object attributes that will be used to create the
+ // Device Handler Object.
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+
+ ObjectSize = PcipDeviceHandlerObjectSize + sizeof (DEVICE_DATA);
+
+ //
+ // Create the object
+ //
+
+ Status = ObCreateObject(
+ KernelMode,
+ *IoDeviceHandlerObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ ObjectSize,
+ 0,
+ 0,
+ (PVOID *) &DeviceHandler
+ );
+
+ if (NT_SUCCESS(Status)) {
+ RtlZeroMemory (DeviceHandler, ObjectSize);
+
+ DeviceHandler->Type = (USHORT) *IoDeviceHandlerObjectType;
+ DeviceHandler->Size = (USHORT) ObjectSize;
+ DeviceHandler->SlotNumber = SlotNumber.u.AsULONG;
+
+ //
+ // Get a reference to the object
+ //
+
+ Status = ObReferenceObjectByPointer(
+ DeviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+ }
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Insert it into the object table
+ //
+
+ Status = ObInsertObject(
+ DeviceHandler,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ NULL,
+ &Handle
+ );
+ }
+
+
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // Object not created correctly
+ //
+
+ ExReleaseFastMutex (&PcipMutex);
+ break;
+ }
+
+ ZwClose (Handle);
+
+
+ //
+ // Intialize structure to track device
+ //
+
+ DebugPrint ((8, "PCI: adding slot %x (for device %04x-%04x)\n",
+ SlotNumber,
+ PciData->VendorID,
+ PciData->DeviceID
+ ));
+
+ DeviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Get BAR decode bits which are supported
+ //
+
+ Status = PcipGetBarBits (DeviceData, PciPort->Handler);
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ DeviceHandler->BusHandler = Handler;
+ HalReferenceBusHandler (Handler);
+
+ DeviceData->Valid = TRUE;
+ PciPort->NoValidSlots += 1;
+ PushEntryList (&PciPort->ValidSlots, &DeviceData->Next);
+ BusCheck = TRUE;
+ }
+
+ //
+ // Obtain an extra reference to the device handler for
+ // sending some DeviceControls
+ //
+
+ ObReferenceObjectByPointer (
+ DeviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+
+ //
+ // If we are installing the initail bus support, then
+ // all devices are installed as locked & powered up.
+ // If this is a dynamically located new device, then
+ // the device is started as unlocked & powered down.
+ //
+
+ if (Initialize) {
+
+ //
+ // Set initial state as locked
+ //
+
+ State = TRUE;
+ BufferSize = sizeof (State);
+ HalDeviceControl (
+ DeviceHandler,
+ NULL,
+ BCTL_SET_LOCK,
+ &State,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+
+ //
+ // Set initial power state as Powered Up
+ //
+
+ PowerState = PowerUp;
+ BufferSize = sizeof (PowerState);
+ HalDeviceControl (
+ DeviceHandler,
+ NULL,
+ BCTL_SET_POWER,
+ (PVOID) &PowerState,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+ }
+
+ //
+ // Free once
+ //
+
+ ObDereferenceObject (DeviceHandler);
+ }
+
+ ExReleaseFastMutex (&PcipMutex);
+ }
+ }
+
+ //
+ // Undo reference to bus handler from top of function
+ //
+
+ HalDereferenceBusHandler (Handler);
+
+ //
+ // Do we need to notify the system buscheck callback?
+ //
+
+ if (BusCheck) {
+ ExNotifyCallback (
+ PciHalCallbacks.BusCheck,
+ (PVOID) PciPort->Handler->InterfaceType,
+ (PVOID) PciPort->Handler->BusNumber
+ );
+ }
+
+}
+
+NTSTATUS
+PcipVerifyBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ )
+{
+ NTSTATUS Status;
+
+ PAGED_CODE ();
+
+ Status = STATUS_SUCCESS;
+ if (!DeviceData->BARBitsSet) {
+
+ DeviceData->BARBitsSet = TRUE;
+ Status = PcipGetBarBits (DeviceData, Handler);
+
+ if (!NT_SUCCESS(Status)) {
+ DeviceData->BARBitsSet = FALSE;
+ }
+ }
+
+ return Status;
+}
+
+
+
+NTSTATUS
+PcipGetBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ )
+{
+ PPCIBUSDATA PciBusData;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress2[PCI_TYPE0_ADDRESSES + 1];
+ ULONG NoBaseAddress2, RomIndex2;
+ ULONG j;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ LONGLONG bits, base, length, max;
+ BOOLEAN BrokenDevice;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE ();
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // Get the device's current configuration
+ //
+
+ if (!DeviceData->CurrentConfig) {
+ DeviceData->CurrentConfig = (PPCI_COMMON_CONFIG)
+ ExAllocatePoolWithTag (NonPagedPool, PCI_COMMON_HDR_LENGTH, 'cICP');
+
+ if (!DeviceData->CurrentConfig) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ RtlCopyMemory (DeviceData->CurrentConfig, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Get BaseAddress array, and check if ROM was originally enabled
+ //
+
+ DeviceData->EnableRom = PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // If the device's current configuration isn't enabled, then set for
+ // not powered on
+ //
+
+ if (!(PciData->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
+ DeviceData->Power = FALSE;
+ DeviceData->Locked = FALSE;
+ }
+
+ //
+ // Check to see if there are any BARs
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ DeviceData->BARBits[j] = 0;
+ if (*BaseAddress[j]) {
+ DeviceData->BARBitsSet = TRUE;
+ }
+ }
+
+ //
+ // If not BarBitsSet, then don't attempt to determine the possible
+ // device settings now
+ //
+
+ if (!DeviceData->BARBitsSet) {
+ DebugPrint ((2, "PCI: ghost added device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber));
+
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Set BARs to all on, and read them back
+ //
+
+ DebugPrint ((3, "PCI: getting valid BAR bits on device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber
+ ));
+
+
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER);
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ DeviceData->CurrentConfig,
+ BaseAddress2,
+ &NoBaseAddress2,
+ &RomIndex2
+ );
+
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ //
+ // Remember the original bits
+ //
+
+ DeviceData->BARBits[j] = *BaseAddress[j];
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ DeviceData->BARBits[j+1] = *BaseAddress[j+1];
+ }
+
+ //
+ // Crack bits & check for BrokenDevice
+ //
+
+ BrokenDevice = PcipCrackBAR (
+ BaseAddress2,
+ DeviceData->BARBits,
+ &j,
+ &base,
+ &length,
+ &max
+ );
+
+ if (BrokenDevice) {
+ DeviceData->BrokenDevice = TRUE;
+ }
+ }
+ }
+
+ if (DeviceData->BrokenDevice) {
+ DebugPrint ((2, "PCI: added defective device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber));
+
+ } else {
+ DebugPrint ((2, "PCI: added device %04x-%04x in slot %x\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ SlotNumber));
+ }
+
+ return STATUS_SUCCESS;
+}
+
+PDEVICE_DATA
+PcipFindDeviceData (
+ IN PPCI_PORT PciPort,
+ IN PCI_SLOT_NUMBER SlotNumber
+ )
+{
+ PDEVICE_DATA DeviceData;
+ PSINGLE_LIST_ENTRY Link;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+
+ PAGED_CODE ();
+
+ for (Link = PciPort->ValidSlots.Next; Link; Link = Link->Next) {
+ DeviceData = CONTAINING_RECORD (Link, DEVICE_DATA, Next);
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+ if (DeviceHandler->SlotNumber == SlotNumber.u.AsULONG) {
+ break;
+ }
+ }
+
+ if (!Link) {
+ return NULL;
+ }
+
+ return DeviceData;
+}
+
+
+BOOLEAN
+PcipCrackBAR (
+ IN PULONG *BaseAddress,
+ IN PULONG BarBits,
+ IN OUT PULONG Index,
+ OUT PLONGLONG pbase,
+ OUT PLONGLONG plength,
+ OUT PLONGLONG pmax
+ )
+{
+ LONGLONG base, length, max, bits;
+ BOOLEAN Status;
+
+ PAGED_CODE ();
+
+ //
+ // Get initial base & bits
+ //
+
+ base = *BaseAddress[*Index];
+ bits = BarBits[*Index];
+
+ if (Is64BitBaseAddress(base)) {
+ *Index += 1;
+ base |= ((LONGLONG) *BaseAddress[*Index]) << 32;
+ bits |= ((LONGLONG) BarBits[*Index]) << 32;
+ }
+
+ //
+ // Scan for first set bit, that's the BARs length and alignment
+ //
+
+ length = (base & PCI_ADDRESS_IO_SPACE) ? 1 << 2 : 1 << 4;
+ while (!(bits & length) && length) {
+ length <<= 1;
+ }
+
+ //
+ // Scan for last set bit, that's that BARs max address + 1
+ //
+
+ for (max = length; bits & max; max <<= 1) ;
+ max -= 1;
+
+ //
+ // Check for defective BAR
+ //
+
+ Status = (bits & ~max) ? TRUE : FALSE;
+
+ //
+ // return results
+ //
+
+ *pbase = base;
+ *plength = length;
+ *pmax = max;
+ return Status;
+}
diff --git a/private/ntos/nthals/extender/pci/control.c b/private/ntos/nthals/extender/pci/control.c
new file mode 100644
index 000000000..2ac6e2b24
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/control.c
@@ -0,0 +1,662 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ control.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipControlWorker)
+#pragma alloc_text(PAGE,PciCtlEject)
+#pragma alloc_text(PAGE,PciCtlLock)
+#pragma alloc_text(PAGE,PciCtlForward)
+#pragma alloc_text(PAGE,PcipCompleteDeviceControl)
+#endif
+
+
+VOID
+PcipStartWorker (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used to verify a worker thread is dispatched
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ULONG WorkerQueued;
+
+ if (!PcipWorkerQueued) {
+ WorkerQueued = ExInterlockedExchangeUlong (
+ &PcipWorkerQueued,
+ 1,
+ PcipSpinLock
+ );
+
+ if (!WorkerQueued) {
+ ExQueueWorkItem (&PcipWorkItem, DelayedWorkQueue);
+ }
+ }
+}
+
+VOID
+PcipQueueCheckBus (
+ PBUS_HANDLER Handler
+ )
+{
+ PPCI_PORT PciPort;
+
+ PciPort = PCIPORTDATA(Handler);
+ ExInterlockedInsertTailList (
+ &PcipCheckBusList,
+ &PciPort->CheckBus,
+ &PcipSpinlock
+ );
+
+ PcipStartWorker();
+}
+
+
+VOID
+PcipControlWorker (
+ IN PVOID WorkerContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called by a system worker thread.
+
+ The worker thread dequeues any DeviceControls which need to be
+ processed and dispatches them.
+
+ It then checks for any
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PLIST_ENTRY Entry;
+ PPCI_PORT PciPort;
+ PHAL_DEVICE_CONTROL_CONTEXT Context;
+
+ PAGED_CODE ();
+
+ //
+ // Dispatch pending slot controls
+ //
+
+ for (; ;) {
+ Entry = ExInterlockedRemoveHeadList (
+ &PcipControlWorkerList,
+ &PcipSpinlock
+ );
+
+ if (!Entry) {
+ break;
+ }
+
+ Context = CONTAINING_RECORD (
+ Entry,
+ HAL_DEVICE_CONTROL_CONTEXT,
+ ContextWorkQueue,
+ );
+
+ PcipDispatchControl (Context);
+ }
+
+ //
+ // Reset worker item for next time
+ //
+
+ ExInitializeWorkItem (&PcipWorkItem, PcipControlWorker, NULL);
+ ExInterlockedExchangeUlong (&PcipWorkerQueued, 0, PcipSpinLock);
+
+ //
+ // Process check buses
+ //
+
+ for (; ;) {
+ Entry = ExInterlockedRemoveHeadList (
+ &PcipCheckBusList,
+ &PcipSpinlock
+ );
+
+ if (!Entry) {
+ break;
+ }
+
+ PciPort = CONTAINING_RECORD (
+ Entry,
+ PCI_PORT,
+ CheckBus
+ );
+
+ PcipCheckBus (PciPort, FALSE);
+ }
+}
+
+
+VOID
+PcipDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function dispatches a DeviceControl to the appropiate handler.
+ If the slot is busy, the DeviceControl may be queued for dispatching at
+ a later time
+
+Arguments:
+
+ Context - The DeviceControl context to dispatch
+
+Return Value:
+
+--*/
+{
+ PDEVICE_CONTROL_HANDLER DeviceControlHandler;
+ PDEVICE_DATA DeviceData;
+ PPCI_PORT PciPort;
+ KIRQL OldIrql;
+ BOOLEAN EnqueueIt;
+ PLIST_ENTRY Link;
+
+ DeviceControlHandler = (PDEVICE_CONTROL_HANDLER) Context->ContextControlHandler;
+ PciPort = PCIPORTDATA(Context->Handler);
+ DeviceData = DeviceHandler2DeviceData (Context->DeviceControl.DeviceHandler);
+
+ //
+ // Get access to the device specific data.
+ //
+
+ KeAcquireSpinLock (&PcipSpinlock, &OldIrql);
+
+ //
+ // Verify the device data is still valid
+ //
+
+ if (!DeviceData->Valid) {
+
+ //
+ // Caller has invalid handle, or handle to a different device
+ //
+
+ DebugPrint ((2, "PCI: DeviceControl has invalid device handler \n" ));
+ Context->DeviceControl.Status = STATUS_NO_SUCH_DEVICE;
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+ HalCompleteDeviceControl (Context);
+ return ;
+ }
+
+ //
+ // Check to see if this request can be begun now
+ //
+
+ Link = (PLIST_ENTRY) &Context->ContextWorkQueue;
+ EnqueueIt = DeviceControlHandler->BeginDeviceControl (DeviceData, Context);
+
+ if (EnqueueIt) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ InsertTailList (&PciPort->DeviceControl, Link);
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+ return ;
+ }
+
+ //
+ // Dispatch the function to it's handler
+ //
+
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+ DeviceControlHandler->ControlHandler (DeviceData, Context);
+}
+
+VOID
+PcipiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData,
+ PBOOLEAN Sync
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a DeviceControl. If another DeviceControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ KIRQL OldIrql;
+ PPCI_PORT PciPort;
+ PLIST_ENTRY Link;
+ PBOOLEAN BusyFlag;
+ BOOLEAN StartWorker;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+
+
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+ BusyFlag = (PBOOLEAN) Context->ContextBusyFlag;
+ PciPort = PCIPORTDATA(Context->Handler);
+
+ //
+ // Pass it to the hal for completion
+ //
+
+ Context->DeviceControl.Status = Status;
+ HalCompleteDeviceControl (Context);
+ StartWorker = FALSE;
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ KeAcquireSpinLock (&PcipSpinlock, &OldIrql);
+
+ //
+ // Clear appropiate busy flag
+ //
+
+ *BusyFlag = FALSE;
+
+ //
+ // Check to see if there are any pending slot controls for
+ // this device. If so, requeue them to the worker thread.
+ // (yes, this code is not efficient, but doing it this way
+ // saves a little on the nonpaged pool device_data structure size)
+ //
+
+ for (Link = PciPort->DeviceControl.Flink; Link != &PciPort->DeviceControl; Link = Link->Flink) {
+ Context = CONTAINING_RECORD (Link, HAL_DEVICE_CONTROL_CONTEXT, ContextWorkQueue);
+ if (Context->DeviceControl.DeviceHandler == DeviceHandler) {
+ RemoveEntryList (Link);
+ InsertTailList (&PcipControlWorkerList, Link);
+ StartWorker = TRUE;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock (&PcipSpinlock, OldIrql);
+
+ if (StartWorker) {
+ PcipStartWorker ();
+ }
+}
+
+VOID
+PcipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a DeviceControl. If another DeviceControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PAGED_CODE();
+
+ PcipiCompleteDeviceControl (
+ Status,
+ Context,
+ DeviceData,
+ &DeviceData->SyncBusy
+ );
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ if ( *((PPOWER_STATE) Context->DeviceControl.Buffer) == PowerUp ) {
+
+ //
+ // This is a power on, there can only be one of these on the
+ // slot at any one time
+ //
+
+ ASSERT (DeviceData->AsyncBusy == FALSE);
+
+ //
+ // If PowerUp needs to pend, then queue the request
+ //
+
+ if (DeviceData->PendPowerUp) {
+ return TRUE;
+ }
+
+ DeviceData->AsyncBusy = TRUE;
+ Context->ContextBusyFlag = (ULONG) &DeviceData->AsyncBusy;
+ return FALSE;
+ }
+
+ //
+ // Something other then a PowerUp. Some form of power down,
+ // treat it like any other sync request
+ //
+
+ return PciBCtlSync (DeviceData, Context);
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlSync (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ //
+ // This is a sync command, verify the slot is not busy with a different
+ // command.
+ //
+
+ if (DeviceData->SyncBusy || DeviceData->AsyncBusy) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ return TRUE;
+ }
+
+ //
+ // Don't enqueue, dispatch it now
+ //
+
+ DeviceData->SyncBusy = TRUE;
+ Context->ContextBusyFlag = (ULONG) &DeviceData->SyncBusy;
+ return FALSE;
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ BOOLEAN Busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ Busy = PciBCtlSync (DeviceData, Context);
+
+ if (!Busy) {
+
+ //
+ // Just trying to eject a device will invalidate the current
+ // device handler object for it...
+ //
+
+ DeviceData->Valid = FALSE;
+ DebugPrint ((5, "PCI: set handle invalid - slot %x\n", DeviceDataSlot(DeviceData)));
+ }
+
+ return Busy;
+}
+
+BOOLEAN
+FASTCALL
+PciBCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ BOOLEAN Busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ Busy = PciBCtlSync (DeviceData, Context);
+ if (!Busy &&
+ ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer) ) {
+
+ //
+ // About to perform an unlock, set PendPowerUp
+ // This will stop any async power up requests
+ //
+
+ ASSERT (DeviceData->PendPowerUp == FALSE);
+ DeviceData->PendPowerUp = TRUE;
+ }
+
+ return Busy;
+}
+
+VOID
+PciCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // We don't know how to lock or unlock, but we track various
+ // device state. Event attempting to ejecting a device effectively
+ // unlocks & powers it down.
+ //
+
+ DeviceData->Locked = FALSE;
+ Status = PcipPowerDownSlot (Context->Handler, DeviceData);
+
+ //
+ // Pass the eject request
+ //
+
+ if (NT_SUCCESS(Status)) {
+ Status = BugBugSubclass ();
+ }
+
+ DebugPrint ((2, "PCI: Eject complete - Slot %x, Status %x\n",
+ DeviceDataSlot(DeviceData), Status));
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+VOID
+PciCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ BOOLEAN Lock;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // We don't know how to lock or unlock, but we track the
+ // device's locked state
+ //
+
+ Lock = ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer)->Control;
+
+ //
+ // If this is an unlock request, powered down the slot
+ //
+
+ Status = STATUS_SUCCESS;
+ if (!Lock) {
+ Status = PcipPowerDownSlot (Context->Handler, DeviceData);
+ }
+
+ //
+ // Pass the lock request to miniport driver to lock/unlock the slot
+ //
+
+ if (NT_SUCCESS(Status)) {
+ Status = BugBugSubclass ();
+ }
+
+ //
+ // If it worked, set the new locked state
+ //
+
+ if (NT_SUCCESS(Status)) {
+ DeviceData->Locked = Lock;
+ }
+
+ //
+ // Allow power requests to continue
+ //
+
+ DeviceData->PendPowerUp = FALSE;
+ DebugPrint ((2, "PCI: %s complete - Slot %x, Status %x\n",
+ Lock ? "Lock" : "Unlock", DeviceDataSlot(DeviceData), Status));
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ POWER_STATE Power;
+ NTSTATUS Status;
+
+ // not pagable
+
+ //
+ // We don't know how to power on or off the device, but we track the
+ // device's power state
+ //
+
+ Power = *((PPOWER_STATE) Context->DeviceControl.Buffer);
+
+ //
+ // If this is a power down request, complete it
+ //
+
+ if (Power != PowerUp) {
+ Status = PcipPowerDownSlot (Context->Handler, DeviceData);
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+ return ;
+ }
+
+ //
+ // Device must be locked, or the power up request should have
+ // received an invalid device error.
+ //
+
+ ASSERT (DeviceData->Locked);
+
+ //
+ // If the device already has power, then there's nothing to do
+ //
+
+ if (DeviceData->Power) {
+ PcipiCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceData, &DeviceData->AsyncBusy);
+ return ;
+ }
+
+ // bugbug pass it to a child driver, for now just complete it
+
+ PcipCompletePowerUp (DeviceData, Context);
+}
+
+VOID
+PcipCompletePowerUp (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ NTSTATUS Status;
+
+ //
+ // Put the device's prior configuration back.
+ //
+
+ DeviceData->Power = TRUE;
+ Status = PcipFlushConfig (Context->Handler, DeviceData);
+
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // The device's state could not be restored. The decodes
+ // for the device shouldn't be enabled, so there's no immidiate
+ // problem. But break the current handle to the device and
+ // kick off a bus check. This will cause us to assign the
+ // device a new handle, and to power it off.
+ //
+
+ DeviceData->Valid = FALSE;
+ PcipQueueCheckBus (Context->Handler);
+ }
+
+ if (Context->DeviceControl.ControlCode == BCTL_SET_POWER) {
+ DebugPrint ((2, "PCI: Powerup complete - Slot %x, Status %x\n",
+ DeviceDataSlot(DeviceData), Status));
+
+ PcipiCompleteDeviceControl (Status, Context, DeviceData, &DeviceData->AsyncBusy);
+ }
+}
+
+
+VOID
+PciCtlForward (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ PAGED_CODE ();
+
+ DbgPrint ("PCI: BUGBUG Forward\n");
+ PcipCompleteDeviceControl (STATUS_NOT_IMPLEMENTED, Context, DeviceData);
+}
diff --git a/private/ntos/nthals/extender/pci/devres.c b/private/ntos/nthals/extender/pci/devres.c
new file mode 100644
index 000000000..578c4ac46
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/devres.c
@@ -0,0 +1,1139 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ Device Resources
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+NTSTATUS
+PcipQueryResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList
+ );
+
+NTSTATUS
+PcipSetResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PCM_RESOURCE_LIST ResourceList,
+ ULONG ListSize
+ );
+
+
+#pragma alloc_text(PAGE,PciCtlQueryDeviceId)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceUniqueId)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceResources)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceResourceRequirements)
+#pragma alloc_text(PAGE,PciCtlSetDeviceResources)
+#pragma alloc_text(PAGE,PciCtlAssignSlotResources)
+#pragma alloc_text(PAGE,PcipQueryResourceRequirements)
+#pragma alloc_text(PAGE,PcipSetResources)
+
+
+
+
+VOID
+PciCtlQueryDeviceId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular slot.
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+ PPCI_COMMON_CONFIG PciData;
+ PWCHAR DeviceID;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ ULONG length;
+ ULONG IDNumber;
+
+ PAGED_CODE();
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Determine which device ID the caller wants back
+ //
+
+ IDNumber = *((PULONG) Context->DeviceControl.Buffer);
+
+ //
+ // For PCI devices:
+ // ID #0 is the specific PCI device ID.
+ // ID #1 is the compatible device ID based on the BaseClass & SubClass fields
+ //
+
+ Status = STATUS_NO_MORE_ENTRIES;
+ DeviceID = (PWCHAR) Context->DeviceControl.Buffer;
+
+ if (IDNumber == 0) {
+
+ //
+ // Return the PCI device ID
+ //
+
+ swprintf (DeviceID, PCI_ID, PciData->VendorID, PciData->DeviceID);
+ Status = STATUS_SUCCESS;
+ }
+
+ if (IDNumber == 1) {
+
+ //
+ // Return the first compatible device id for the device
+ //
+
+ if ( (PciData->BaseClass == 0 &&
+ PciData->SubClass == 1 &&
+ PciData->ProgIf == 0) ||
+
+ (PciData->BaseClass == 3 &&
+ PciData->SubClass == 0 &&
+ PciData->ProgIf == 0) ) {
+
+ //
+ // This is an industry standard VGA controller
+ //
+
+ swprintf (DeviceID, PNP_VGA);
+ Status = STATUS_SUCCESS;
+ }
+
+ if (PciData->BaseClass == 1 &&
+ PciData->SubClass == 0 &&
+ PciData->ProgIf == 0) {
+
+ //
+ // This is an industry standard IDE controller
+ //
+
+ swprintf (DeviceID, PNP_IDE);
+ Status = STATUS_SUCCESS;
+
+ }
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlQueryDeviceUniqueId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns a unique device id for the particular slot.
+ The id is a sequence of numbers separated by dots ('.'). The first
+ number is the bus number of the root of the heirarchy of PCI buses
+ that the slot belongs to. The last number in the sequence is the
+ slot number in question. A possibly empty set of numbers in between
+ these two, represents the slot numbers of intermediate PCI-PCI bridges
+ in the hierarchy between the root bus and the slot.
+
+ For example, L"0.1.2.3":
+ 0 PCI bus number of the root of the heirarchy.
+ 1 Slot number within PCI bus 0 were a PCI-PCI bridge is
+ located, the secondary bus that it bridges to is PCI bus X.
+ 2 Slot number within PCI bus X were a PCI-PCI bridge is
+ located, the secondary bus that it bridges to is PCI bus Y.
+ 3 Slot number within PCI bus Y for which we are wanting to
+ obtain the unique id (i.e. the targer of this control operation).
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+ PBUS_HANDLER BusHandler;
+ PBUS_HANDLER ParentHandler;
+ PWCHAR UniqueDeviceId;
+ PWCHAR UniqueDeviceIdEnd;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ BOOLEAN Done;
+ UCHAR UidComponent;
+ PPCIBUSDATA PciBusData;
+ PWCHAR DelimiterPointer;
+ WCHAR Delimiter;
+
+ PAGED_CODE();
+
+ //
+ // Set [UniqueDeviceId, UniqueDeviceIdEnd) to the range of
+ // wide characters for which the caller provided storage.
+ //
+
+ Status = STATUS_SUCCESS;
+ UniqueDeviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ UniqueDeviceIdEnd = UniqueDeviceId
+ + *Context->DeviceControl.BufferLength / sizeof(WCHAR);
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+
+ //
+ // Determine the memory required for the unique id.
+ // Note that this loop exits in the middle and that it will
+ // always be executed at least 1.5 times. If there are PCI-PCI
+ // bridges between the slot's bus and the root bus of the PCI
+ // hierarchy, then an extra iteration of the loop will be done
+ // for each one of them.
+ //
+ // The bus hierarchy is being walked backwards (from leaf to root).
+ // Finally, note that the rightmost uid component is the slot's
+ // number (set before we enter the loop).
+ //
+
+ BusHandler = DeviceHandler->BusHandler;
+ UidComponent = (UCHAR) DeviceHandler->SlotNumber;
+ Done = FALSE;
+
+ for (;;) {
+
+ //
+ // On each iteration, given the value of one of the components of
+ // the unique id, determine how much memory the swprintf would use
+ // for it (note that the 2, 3 & 4 below include a +1, which is
+ // for the nul terminator or for the '.' delimiter between two
+ // unique id components.
+ //
+
+ if (UidComponent <= 9) {
+ UniqueDeviceId += 2;
+ } else if (UidComponent <= 99) {
+ UniqueDeviceId += 3;
+ } else {
+ UniqueDeviceId += 4;
+ }
+
+ if (Done) {
+ break;
+ }
+
+ //
+ // If there is no parent bus handler for the current bus,
+ // or if it is not a PCI bus, then we are at the root of
+ // this hierarchy of PCI buses. In this case the unique id
+ // component is the bus number (instead of a slot number),
+ // furthermore, we are almost done (just account for the
+ // space required in the unique id for it).
+ //
+ // Otherwise, the current bus is a PCI-PCI bridge and its
+ // unique id component is the slot number of the bridge
+ // within its parent bus.
+ //
+
+ ParentHandler = BusHandler->ParentHandler;
+ if (!ParentHandler || ParentHandler->InterfaceType != PCIBus) {
+ UidComponent = (UCHAR) BusHandler->BusNumber;
+ Done = TRUE;
+ } else {
+ PciBusData = (PPCIBUSDATA) BusHandler->BusData;
+ UidComponent = (UCHAR) PciBusData->ParentSlot.u.AsULONG;
+ BusHandler = ParentHandler;
+ }
+ }
+
+ //
+ // If there is not enough space for the unique id, fail
+ // and return the size required.
+ //
+
+ if (UniqueDeviceId > UniqueDeviceIdEnd) {
+ *Context->DeviceControl.BufferLength = (UniqueDeviceIdEnd
+ - (PWCHAR) Context->DeviceControl.Buffer) * sizeof(WCHAR);
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+
+ //
+ // Otherwise, traverse the bus heirarchy again (just like
+ // above), except that this time we decrement the UniqueDeviceId
+ // on each iteration and swprintf the uid component. Note that
+ // for all components except for the right most one we store
+ // a delimiter after it (i.e. a '.').
+ //
+
+ BusHandler = DeviceHandler->BusHandler;
+ UidComponent = (UCHAR) DeviceHandler->SlotNumber;
+ Done = FALSE;
+ Delimiter = L'\0';
+ for (;;) {
+ DelimiterPointer = UniqueDeviceId;
+ if (UidComponent <= 9) {
+ UniqueDeviceId -= 2;
+ } else if (UidComponent <= 99) {
+ UniqueDeviceId -= 3;
+ } else {
+ UniqueDeviceId -= 4;
+ }
+ swprintf(UniqueDeviceId, L"%d", UidComponent);
+ DelimiterPointer[-1] = Delimiter;
+ Delimiter = L'.';
+
+ if (Done) {
+ break;
+ }
+
+ ParentHandler = BusHandler->ParentHandler;
+ if (!ParentHandler || ParentHandler->InterfaceType != PCIBus) {
+ UidComponent = (UCHAR) BusHandler->BusNumber;
+ Done = TRUE;
+ } else {
+ PciBusData = (PPCIBUSDATA) BusHandler->BusData;
+ UidComponent = (UCHAR) PciBusData->ParentSlot.u.AsULONG;
+ BusHandler = ParentHandler;
+ }
+ }
+ }
+
+ PcipCompleteDeviceControl(Status, Context, DeviceData);
+}
+
+
+VOID
+PciCtlQueryDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCES DeviceControl
+ which returns the bus resources being used by the specified device
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PCM_RESOURCE_LIST CompleteList;
+ PCM_PARTIAL_RESOURCE_LIST PartialList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ LONGLONG base, length, max;
+ NTSTATUS Status;
+ PUCHAR WorkingPool;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+// BUGBUG if the device is a pci-2-pci bus controller, then
+// this function should return the addresses which are bridged
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ PcipCompleteDeviceControl (STATUS_INSUFFICIENT_RESOURCES, Context, DeviceData);
+ return ;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Build a CM_RESOURCE_LIST for the PCI device
+ //
+
+ CompleteList->Count = 1;
+ CompleteList->List[0].InterfaceType = Context->RootHandler->InterfaceType;
+ CompleteList->List[0].BusNumber = Context->RootHandler->BusNumber;
+
+ PartialList = &CompleteList->List[0].PartialResourceList;
+ Descriptor = PartialList->PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+
+ PciBusData->Pin2Line (
+ Context->Handler,
+ Context->RootHandler,
+ SlotNumber,
+ PciData
+ );
+
+ Descriptor->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
+
+ PartialList->Count++;
+ Descriptor++;
+ }
+
+ //
+ // Add any memory / port resources being used
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ ASSERT (DeviceData->BARBitsSet);
+ PcipCrackBAR (BaseAddress, DeviceData->BARBits, &j, &base, &length, &max);
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+
+ if (PciData->Command & PCI_ENABLE_IO_SPACE) {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Port.Start.QuadPart = base & ~0x3;
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Port.Length = (ULONG) length;
+ }
+
+
+ } else {
+
+ if (PciData->Command & PCI_ENABLE_MEMORY_SPACE) {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == RomIndex) {
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (base & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ Descriptor->u.Memory.Start.QuadPart = base & ~0xF;
+ ASSERT (length < 0xFFFFFFFF);
+ Descriptor->u.Memory.Length = (ULONG) length;
+ }
+ }
+
+ PartialList->Count++;
+ Descriptor++;
+ }
+ }
+
+ //
+ // Return results
+ //
+
+ i = (ULONG) ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+ if (i > *Context->DeviceControl.BufferLength) {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, CompleteList, i);
+ Status = STATUS_SUCCESS;
+ }
+
+ *Context->DeviceControl.BufferLength = i;
+ ExFreePool (WorkingPool);
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlQueryDeviceResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCE_REQUIREMENTS DeviceControl
+ which returns the possible bus resources that this device may be
+ satisfied with.
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipQueryResourceRequirements (DeviceData, Context, &ResourceList);
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Return results
+ //
+
+ if (ResourceList->ListSize > *Context->DeviceControl.BufferLength) {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, ResourceList, ResourceList->ListSize);
+ Status = STATUS_SUCCESS;
+ }
+
+ *Context->DeviceControl.BufferLength = ResourceList->ListSize;
+
+ }
+
+ if (ResourceList) {
+ ExFreePool (ResourceList);
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+NTSTATUS
+PcipQueryResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList
+ )
+/*++
+
+Routine Description:
+
+ This function allocates and returns the specified devices
+ IO_RESOURCE_REQUIREMENTS_LIST
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ LONGLONG base, length, max;
+ NTSTATUS Status;
+ PUCHAR WorkingPool;
+
+ PAGED_CODE();
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ *ResourceList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ if (!*ResourceList) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = Context->RootHandler->InterfaceType;
+ CompleteList->BusNumber = Context->RootHandler->BusNumber;
+ CompleteList->SlotNumber = DeviceDataSlot(DeviceData);
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+
+ // BUGBUG: this is not correct
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+
+ //
+ // Add any memory / port resources being used
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ PcipCrackBAR (BaseAddress, DeviceData->BARBits, &j, &base, &length, &max);
+
+ //
+ // Add a descriptor for this address
+ //
+
+ Descriptor->Option = 0;
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Port.Alignment = (ULONG) length;
+ Descriptor->u.Port.Length = (ULONG) length;
+ Descriptor->u.Port.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = max;
+
+ } else {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (base & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Memory.Alignment = (ULONG) length;
+ Descriptor->u.Memory.Length = (ULONG) length;
+ Descriptor->u.Memory.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Memory.MaximumAddress.QuadPart = max;
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+ }
+
+ if (DeviceData->BrokenDevice) {
+
+ //
+ // This device has something wrong with its base address register implementation
+ //
+
+ ExFreePool (WorkingPool);
+ return STATUS_DEVICE_PROTOCOL_ERROR;
+ }
+
+ //
+ // Return results
+ //
+
+ CompleteList->ListSize = (ULONG) ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+ *ResourceList = CompleteList;
+ return STATUS_SUCCESS;
+}
+
+VOID
+PciCtlSetDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the SET_DEVICE_RESOURCES DeviceControl
+ which configures the device to the specified device setttings
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipSetResources (
+ DeviceData,
+ Context,
+ (PCM_RESOURCE_LIST) Context->DeviceControl.Buffer,
+ *Context->DeviceControl.BufferLength
+ );
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+NTSTATUS
+PcipSetResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PCM_RESOURCE_LIST ResourceList,
+ ULONG ListSize
+ )
+/*++
+
+Routine Description:
+
+ This function set the specified device to the CM_RESOURCE_LIST
+
+Arguments:
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ LONGLONG base, length;
+ NTSTATUS Status;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // If BARBits haven't been deteremined, go do it now
+ //
+
+ Status = PcipVerifyBarBits (DeviceData, Context->Handler);
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+
+ //
+ // Get current device configuration
+ //
+
+ if (DeviceData->Power) {
+ ASSERT (DeviceData->CurrentConfig == NULL);
+ DeviceData->CurrentConfig = (PPCI_COMMON_CONFIG)
+ ExAllocatePool (NonPagedPool, PCI_COMMON_HDR_LENGTH);
+
+ if (!DeviceData->CurrentConfig) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciData = DeviceData->CurrentConfig;
+ PciOrigData = (PPCI_COMMON_CONFIG) buffer;
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Save current config
+ //
+
+ RtlCopyMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ //
+ // Assign the interrupt line
+ //
+
+ if (CmDescriptor->Type != CmResourceTypeInterrupt) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+
+ PciBusData->Pin2Line (
+ Context->Handler,
+ Context->RootHandler,
+ SlotNumber,
+ PciData
+ );
+
+ CmDescriptor++;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ base = *BaseAddress[j];
+ if (base) {
+ //
+ // Set 32bits and mask
+ //
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ if (CmDescriptor->Type != CmResourceTypePort) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+
+ } else {
+ if (CmDescriptor->Type != CmResourceTypeMemory) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+
+ if (Is64BitBaseAddress(base)) {
+
+ //
+ // Set upper 32bits
+ //
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j+1] = CmDescriptor->u.Port.Start.HighPart;
+ } else {
+ *BaseAddress[j+1] = CmDescriptor->u.Memory.Start.HighPart;
+ }
+
+ j++;
+ }
+
+ CmDescriptor++;
+ }
+ }
+
+ //
+ // Enabel decodes and set the new addresses
+ //
+
+ if (DeviceData->EnableRom && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ }
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ //
+ // If the device is powered on, flush the cached config information
+ // to the device; otherwise, leave the new configuration in memory -
+ // it will get flushed to the device when it's powered on
+ //
+
+ Status = STATUS_SUCCESS;
+ if (DeviceData->Power) {
+ Status = PcipFlushConfig (Context->Handler, DeviceData);
+ }
+
+CleanUp:
+ //
+ // If there was an error, and the device still has a cached current
+ // config, put the configuration back as it was when we found it
+ //
+
+ if (!NT_SUCCESS (Status) && DeviceData->CurrentConfig) {
+ RtlCopyMemory (DeviceData->CurrentConfig, PciOrigData, PCI_COMMON_HDR_LENGTH);
+ }
+
+ return Status;
+}
+
+
+VOID
+PciCtlAssignSlotResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the internal AssignSlotResources DeviceControl
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+ PCTL_ASSIGN_RESOURCES AssignResources;
+ PCM_RESOURCE_LIST AllocatedResources;
+ NTSTATUS Status;
+ ULONG l;
+ POWER_STATE PowerControl;
+
+ PAGED_CODE();
+
+ ResourceList = NULL;
+ AllocatedResources = NULL;
+ AssignResources = (PCTL_ASSIGN_RESOURCES) Context->DeviceControl.Buffer;
+
+ //
+ // If BARBits haven't been deteremined, go do it now
+ //
+
+ Status = PcipVerifyBarBits (DeviceData, Context->Handler);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipQueryResourceRequirements (DeviceData, Context, &ResourceList);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Get device settings from IO
+ //
+
+ Status = IoAssignResources (
+ AssignResources->RegistryPath,
+ AssignResources->DriverClassName,
+ AssignResources->DriverObject,
+ Context->DeviceControl.DeviceObject,
+ ResourceList,
+ &AllocatedResources
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Set the resources into the device
+ //
+
+ Status = PcipSetResources (DeviceData, Context, AllocatedResources, 0xFFFFFFFF);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Turn the device on
+ //
+
+ PowerControl = PowerUp;
+ l = sizeof (PowerControl);
+
+ Status = HalDeviceControl (
+ Context->DeviceControl.DeviceHandler,
+ Context->DeviceControl.DeviceObject,
+ BCTL_SET_POWER,
+ &PowerControl,
+ &l,
+ NULL,
+ NULL
+ );
+
+CleanUp:
+ *AssignResources->AllocatedResources = AllocatedResources;
+
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (AllocatedResources) {
+ IoAssignResources (
+ AssignResources->RegistryPath,
+ AssignResources->DriverClassName,
+ AssignResources->DriverObject,
+ Context->DeviceControl.DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (AllocatedResources);
+ *AssignResources->AllocatedResources = NULL;
+ }
+ }
+
+ if (ResourceList) {
+ ExFreePool (ResourceList);
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
diff --git a/private/ntos/nthals/extender/pci/init.c b/private/ntos/nthals/extender/pci/init.c
new file mode 100644
index 000000000..f33acf18f
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/init.c
@@ -0,0 +1,357 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+ initialization code for pciport.sys
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "pciport.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(PAGE,PciPortInitialize)
+#endif
+
+#if DBG
+VOID
+PcipTestIds (
+ PBUS_HANDLER PciBus
+ )
+{
+ NTSTATUS Status;
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG Device, Function;
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PDEVICE_DATA DeviceData;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ ULONG BufferSize;
+ PWCHAR Wptr;
+ WCHAR Wchar;
+ WCHAR DeviceId[64];
+ PPCI_PORT PciPort;
+
+ PAGED_CODE();
+
+ PciPort = PciBus->DeviceObject->DeviceExtension;
+ PciBusData = (PPCIBUSDATA) (PciBus->BusData);
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ SlotNumber.u.AsULONG = 0;
+ for (Device=0; Device < PCI_MAX_DEVICES; Device++) {
+ SlotNumber.u.bits.DeviceNumber = Device;
+ for (Function=0; Function < PCI_MAX_FUNCTION; Function++) {
+ SlotNumber.u.bits.FunctionNumber = Function;
+
+ //
+ // Read in the device id
+ //
+
+ PciBusData->ReadConfig (
+ PciBus,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // If not valid, skip it
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0 ||
+ (PCI_CONFIG_TYPE(PciData) != PCI_DEVICE_TYPE &&
+ PCI_CONFIG_TYPE(PciData) != PCI_BRIDGE_TYPE)) {
+ break;
+ }
+
+ DeviceData = PcipFindDeviceData (PciPort, SlotNumber);
+ ASSERT(DeviceData);
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+
+ BufferSize = sizeof (DeviceId);
+ Status = HalDeviceControl (
+ DeviceHandler,
+ NULL,
+ BCTL_QUERY_DEVICE_UNIQUE_ID,
+ DeviceId,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+
+ ASSERT(NT_SUCCESS(Status));
+ DebugPrint ((2, "PCI: Device Unique ID: "));
+ for (Wptr = DeviceId; Wchar = *Wptr++; ) {
+ char buf[2];
+ buf[0] = (char) Wchar;
+ buf[1] = 0;
+ DebugPrint ((2, buf));
+ }
+ DebugPrint ((2, "\n"));
+ }
+ }
+}
+#endif // DBG
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ Finds any currently installed PCI buses and initializes them as
+ pci miniport drivers
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PDEVICE_OBJECT DeviceObject;
+ PBUS_HANDLER PciBus;
+ NTSTATUS Status;
+ UNICODE_STRING unicodeString;
+ ULONG BusNo, junk;
+ BOOLEAN Install;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PCALLBACK_OBJECT CallbackObject;
+
+
+ PciDriverObject = DriverObject;
+
+ //
+ // Add IRP handler for IRPs we care about
+ //
+
+ // DriverObject->MajorFunction[IRP_MJ_CREATE] =
+ // DriverObject->MajorFunction[IRP_MJ_CLOSE] =
+ // DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
+ // DriverObject->MajorFunction[IRP_MJ_SET_POWER] =
+
+ //
+ // Initialize globals
+ //
+
+ ExInitializeWorkItem (&PcipWorkItem, PcipControlWorker, NULL);
+ KeInitializeSpinLock (&PcipSpinlock);
+ InitializeListHead (&PcipControlWorkerList);
+ InitializeListHead (&PcipControlDpcList);
+ InitializeListHead (&PcipCheckBusList);
+ ExInitializeFastMutex (&PcipMutex);
+ ASSERT(PcipMutex.Owner == NULL);
+ PcipDeviceHandlerObjectSize = *IoDeviceHandlerObjectSize;
+
+ //
+ // Register on system suspend/hibernate callback
+ //
+
+ RtlInitUnicodeString(&unicodeString, rgzSuspendCallbackName);
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ Status = ExCreateCallback (&CallbackObject, &ObjectAttributes, FALSE, FALSE);
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ PciSuspendRegistration = ExRegisterCallback (
+ CallbackObject,
+ PcipSuspendNotification,
+ NULL
+ );
+
+ ObDereferenceObject (CallbackObject);
+
+ //
+ // Get access to the HAL callback objects
+ //
+
+ HalQuerySystemInformation (
+ HalCallbackInformation,
+ sizeof (PciHalCallbacks),
+ &PciHalCallbacks,
+ &junk
+ );
+
+ //
+ // For each installed PCI bus
+ //
+
+ _asm int 3;
+
+ Install = FALSE;
+ for (BusNo=0; TRUE; BusNo += 1) {
+ PciBus = HalHandlerForBus (PCIBus, BusNo);
+
+ if (!PciBus) {
+ break;
+ }
+
+ Status = PciPortInitialize (PciBus);
+ if (NT_SUCCESS(Status)) {
+ Install = TRUE;
+ }
+ }
+
+ if (Install) {
+ DebugPrint ((1, "PCI: Installed\n"));
+#if DBG
+ for (BusNo=0; PciBus = HalHandlerForBus (PCIBus, BusNo); BusNo += 1) {
+ PcipTestIds(PciBus);
+ }
+#endif
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Not installing - uninitialize
+ //
+
+ DebugPrint ((1, "PCI: No internal PCI buses found - not installing\n"));
+ ExUnregisterCallback (PciSuspendRegistration);
+
+ return STATUS_NO_SUCH_DEVICE;
+}
+
+
+NTSTATUS
+PciPortInitialize (
+ PBUS_HANDLER PciBus
+ )
+{
+ PPCIBUSDATA PciBusData;
+ PDEVICE_OBJECT BusDeviceObject;
+ WCHAR buffer[100];
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ UNICODE_STRING unicodeString;
+ PPCI_PORT PciPort;
+
+ PAGED_CODE();
+
+ //
+ // Verify bus handler is a PCI miniport driver
+ //
+
+ PciBusData = (PPCIBUSDATA) PciBus->BusData;
+ if (PciBus->InterfaceType != PCIBus ||
+ PciBus->ConfigurationType != PCIConfiguration ||
+ !PciBusData ||
+ PciBusData->Tag != PCI_DATA_TAG ||
+ PciBusData->Version != PCI_DATA_VERSION) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Create device object for this bus extention
+ //
+
+ swprintf (buffer, rgzPCIDeviceName, PciBus->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ Status = IoCreateDevice(
+ PciDriverObject,
+ sizeof (PCI_PORT),
+ &unicodeString,
+ FILE_DEVICE_BUS_EXTENDER,
+ 0,
+ FALSE,
+ &BusDeviceObject
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ DebugPrint ((1, "PCI: Adding PCI bus %d\n", PciBus->BusNumber));
+
+ //
+ // Install pointer to pci extension structure
+ //
+
+ PciBusData->Version = 0;
+ PciBusData->PciExtension = (PVOID) BusDeviceObject->DeviceExtension;
+ PciBus->DeviceObject = BusDeviceObject;
+
+ //
+ // Initialize internal pci port structure
+ //
+
+ PciPort = (PPCI_PORT) BusDeviceObject->DeviceExtension;
+ RtlZeroMemory (PciPort, sizeof (PCI_PORT));
+ PciPort->Handler = PciBus;
+ InitializeListHead (&PciPort->CheckBus);
+ InitializeListHead (&PciPort->DeviceControl);
+
+ //
+ // Intall bus specific handlers
+ //
+
+ PciBus->GetBusData = (PGETSETBUSDATA) PcipGetBusData;
+ PciBus->SetBusData = (PGETSETBUSDATA) PcipSetBusData;
+ PciBus->AssignSlotResources = (PASSIGNSLOTRESOURCES) PcipAssignSlotResources;
+ PciBus->QueryBusSlots = (PQUERY_BUS_SLOTS) PcipQueryBusSlots;
+ PciBus->DeviceControl = (PDEVICE_CONTROL) PcipDeviceControl;
+ PciBus->ReferenceDeviceHandler = (PREFERENCE_DEVICE_HANDLER) PcipReferenceDeviceHandler;
+ PciBus->GetDeviceData = (PGET_SET_DEVICE_DATA) PcipGetDeviceData;
+ PciBus->SetDeviceData = (PGET_SET_DEVICE_DATA) PcipSetDeviceData;
+ PciBus->HibernateBus = (PHIBERNATEBRESUMEBUS) PcipHibernateBus;
+ PciBus->ResumeBus = (PHIBERNATEBRESUMEBUS) PcipResumeBus;
+
+ //
+ // We don't need power control irps - we'll handle all system power
+ // requests via the SystemSuspendHiberante callback and the
+ // bus extender Hibernate & Resume bus entry points
+ //
+
+ BusDeviceObject->DeviceObjectExtension->PowerControlNeeded = FALSE;
+
+ //
+ // BUGBUG: we need to report the resources this PCI bus is using
+ //
+
+ //
+ // Perform initial bus check
+ //
+
+ PcipCheckBus (PciPort, TRUE);
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pci/makefile b/private/ntos/nthals/extender/pci/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/extender/pci/misc.c b/private/ntos/nthals/extender/pci/misc.c
new file mode 100644
index 000000000..beffbc80b
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/misc.c
@@ -0,0 +1,544 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipReadConfig)
+#pragma alloc_text(PAGE,PcipPowerDownSlot)
+#endif
+
+NTSTATUS
+PcipPowerDownSlot (
+ PBUS_HANDLER Handler,
+ PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function is called to power down a particular slot.
+
+Arguments:
+
+Return Value:
+
+ returns once the slot has powered down
+
+--*/
+{
+ USHORT Command;
+ PPCIBUSDATA PciBusData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // If already powered down, do nothing
+ //
+
+ if (!DeviceData->Power) {
+ return STATUS_SUCCESS;
+ }
+
+ DebugPrint ((2, "PCI: Powering down device - slot %d\n", SlotNumber ));
+
+ //
+ // Allocate buffer to save current device configuration
+ //
+
+ ASSERT (DeviceData->CurrentConfig == NULL);
+ DeviceData->CurrentConfig = (PPCI_COMMON_CONFIG)
+ ExAllocatePoolWithTag (NonPagedPool, PCI_COMMON_HDR_LENGTH, 'cICP');
+
+ if (!DeviceData->CurrentConfig) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Read the current configuration
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ DeviceData->CurrentConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // Power down the device
+ //
+
+ DeviceData->Power = FALSE;
+
+ // BUGBUG: should pass this request on
+
+ //
+ // Emulate a powered down device by turning off the device decodes
+ //
+
+ Command = DeviceData->CurrentConfig->Command;
+ Command &= ~(PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER);
+
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ &Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Command)
+ );
+
+ DebugPrint ((2, "PCI: Powerdown complete - Slot %x, Status %x\n",
+ SlotNumber, STATUS_SUCCESS));
+
+ return STATUS_SUCCESS;
+}
+
+
+
+NTSTATUS
+PcipPowerUpSlot (
+ PBUS_HANDLER Handler,
+ PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function is called to power down a particular slot.
+
+Arguments:
+
+Return Value:
+
+ returns once the slot has powered down
+
+--*/
+{
+ //
+ // If already powered up, do nothing
+ //
+
+ if (!DeviceData->Power) {
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Power up the device
+ //
+
+ DebugPrint ((2, "PCI: Powering up device - slot %d\n", DeviceDataSlot(DeviceData) ));
+
+ DeviceData->Power = TRUE;
+
+ // BUGBUG: should pass this request on
+
+}
+
+
+
+VOID
+PcipReadConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData,
+ OUT PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+Routine Description:
+
+ This function returns the current PCI_COMMON_HDR for the device.
+ If the device is powered off, then the pci_common_hdr is returned
+ from it's memory image; otherwise, it is read from the device.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot (DeviceData);
+
+ if (!DeviceData->Power) {
+
+ //
+ // The slot is powered down, return the devices
+ // current configuration from memory
+ //
+
+ RtlCopyMemory (PciData, DeviceData->CurrentConfig, PCI_COMMON_HDR_LENGTH);
+ return ;
+ }
+
+ //
+ // Read the devices current configuration from the device
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+}
+
+NTSTATUS
+PcipFlushConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData
+ )
+/*++
+
+Routine Description:
+
+ This function flushes the cached configuration to the PCI device.
+ It properly handles disabling & enabling of the memory & io decodes,
+ and verifies the new base address register settings. If the device
+ does not take the new settings, if the original settings are known
+ they are put back into the device.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ USHORT HoldCommand;
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ NTSTATUS Status;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PciBusData = (PPCIBUSDATA) (Handler->BusData);
+ PciData2 = (PPCI_COMMON_CONFIG) buffer;
+ PciData = DeviceData->CurrentConfig;
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // To flush the settings, the device must be in the powered on state
+ //
+
+ ASSERT (DeviceData->Power);
+
+ //
+ // Read what is currently in the device
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData2,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // Had better be correct device
+ //
+
+ ASSERT (PciData->VendorID == PciData2->VendorID);
+ ASSERT (PciData->DeviceID == PciData2->DeviceID);
+
+ //
+ // If decodes aren't the same, then clear decode enables before
+ // performing initial set
+ //
+
+ HoldCommand = DeviceData->CurrentConfig->Command;
+ if (!PcipCompareDecodes (DeviceData, PciData, PciData2)) {
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER);
+ }
+
+ //
+ // Write the current device condifuragtion
+ //
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ DeviceData->CurrentConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // Read back the configuration and verify it took
+ //
+
+ PciBusData->ReadConfig (
+ Handler,
+ SlotNumber,
+ PciData2,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // See if configuration matches
+ //
+
+ if (!PcipCompareDecodes (DeviceData, PciData, PciData2)) {
+
+ //
+ // The CurrentConfig did not get successfully set
+ //
+
+ DebugPrint ((1, "PCI: defective device - slot %d\n", SlotNumber));
+ DeviceData->BrokenDevice = TRUE;
+ Status = STATUS_DEVICE_PROTOCOL_ERROR;
+
+ } else {
+
+ //
+ // Settings are fine - write final decode enable bits
+ //
+
+ PciBusData->WriteConfig (
+ Handler,
+ SlotNumber,
+ &HoldCommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (HoldCommand)
+ );
+
+ Status = STATUS_SUCCESS;
+ }
+
+ //
+ // Current config now flushed to the device. Free memory.
+ //
+
+ if (DeviceData->CurrentConfig) {
+ ExFreePool (DeviceData->CurrentConfig);
+ DeviceData->CurrentConfig = NULL;
+ }
+
+ return Status;
+}
+
+BOOLEAN
+PcipCompareDecodes (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ IN PPCI_COMMON_CONFIG PciData2
+ )
+/*++
+
+Routine Description:
+
+ This function compares the base address registers of PciData and PciData2.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG BaseAddress2[PCI_TYPE0_ADDRESSES + 1];
+ ULONG NoBaseAddress, RomIndex;
+ ULONG NoBaseAddress2, RomIndex2;
+ ULONG i, j;
+ BOOLEAN Match;
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData2,
+ BaseAddress2,
+ &NoBaseAddress2,
+ &RomIndex2
+ );
+
+ if (NoBaseAddress != NoBaseAddress2 ||
+ RomIndex != RomIndex2) {
+ return FALSE;
+ }
+
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) != (*BaseAddress2[j] & i)) {
+ Match = FALSE;
+ }
+
+ if (Is64BitBaseAddress(*BaseAddress[j])) {
+ j++;
+ if ((*BaseAddress[j] & i) != (*BaseAddress2[j] & i)) {
+ Match = FALSE;
+ }
+ }
+ }
+ }
+
+ return Match;
+}
+
+
+
+BOOLEAN
+PcipCalcBaseAddrPointers (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ OUT PULONG *BaseAddress,
+ OUT PULONG NoBaseAddress,
+ OUT PULONG RomIndex
+ )
+/*++
+
+Routine Description:
+
+ This function returns the an array of BaseAddress pointers
+ in PciData.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ULONG j;
+ BOOLEAN RomEnabled;
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case PCI_DEVICE_TYPE:
+ *NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ *RomIndex = j;
+ break;
+
+ case PCI_BRIDGE_TYPE:
+ *NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ *RomIndex = j;
+ break;
+
+ default:
+
+ // BUGBUG: unkown type
+
+ *NoBaseAddress = 0;
+ ASSERT (*NoBaseAddress);
+ }
+
+ RomEnabled = (*BaseAddress[*RomIndex] & PCI_ROMADDRESS_ENABLED) ? TRUE : FALSE;
+
+ //
+ // The device's Rom Base Address register is only enabled if it
+ // was originaly found that way.
+ //
+
+ // Clear ROM reserved bits
+ *BaseAddress[*RomIndex] &= ~0x7FF;
+
+ if (!DeviceData->EnableRom) {
+ ASSERT (*RomIndex+1 == *NoBaseAddress);
+ *NoBaseAddress -= 1;
+ }
+
+ return RomEnabled;
+}
+
+
+#if DBG
+ULONG ApmDebug = 9;
+
+VOID
+PciDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ if (Level <= ApmDebug) {
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ }
+
+ va_end(ap);
+}
+#endif
+
+
+
+NTSTATUS
+BugBugSubclass (
+ VOID
+ )
+{
+ DbgPrint ("PCI: BUGBUG SUBCLASS\n");
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pci/pcidata.c b/private/ntos/nthals/extender/pci/pcidata.c
new file mode 100644
index 000000000..b6783c526
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/pcidata.c
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "pciport.h"
+
+//
+// PcipWorkdListLock - Lock to protect DeviceControl globals
+// PcipControlWorkerList - List of slot control's which are pending for worker thread
+// PcipControlDpcList - List of slot control's which are waiting, but are non-paged
+// PcipWorkItem - Enqueue for DeviceControl worker thread
+// PcipWorkDpc - Enqueue for DeviceControl DPC
+//
+
+FAST_MUTEX PcipMutex;
+KSPIN_LOCK PcipSpinlock;
+LIST_ENTRY PcipControlWorkerList;
+LIST_ENTRY PcipControlDpcList;
+LIST_ENTRY PcipCheckBusList;
+ULONG PcipWorkerQueued;
+WORK_QUEUE_ITEM PcipWorkItem;
+KDPC PcipWorkDpc;
+ULONG PcipDeviceHandlerObjectSize;
+
+//
+// DeviceControl dispatch table
+//
+
+#define B_EJECT BCTL_EJECT
+#define B_ID BCTL_QUERY_DEVICE_ID
+#define B_UID BCTL_QUERY_DEVICE_UNIQUE_ID
+#define B_CAPABILITIES BCTL_QUERY_DEVICE_CAPABILITIES
+#define B_RES BCTL_QUERY_DEVICE_RESOURCES
+#define B_RES_REQ BCTL_QUERY_DEVICE_RESOURCE_REQUIREMENTS
+#define B_QUERY_EJECT BCTL_QUERY_EJECT
+#define B_SET_LOCK BCTL_SET_LOCK
+#define B_SET_POWER BCTL_SET_POWER
+#define B_SET_RESUME BCTL_SET_RESUME
+#define B_SET_RES BCTL_SET_DEVICE_RESOURCES
+#define B_ASSIGN_RES BCTL_ASSIGN_SLOT_RESOURCES
+
+#define SIZE_BRES sizeof(CTL_ASSIGN_RESOURCES)
+#define SIZE_CAP sizeof(BCTL_DEVICE_CAPABILITIES)
+#define SIZE_CALL sizeof(PCALLBACK_OBJECT)
+
+DEVICE_CONTROL_HANDLER PcipControl[] = {
+ B_EJECT, 0, PciBCtlEject, PciCtlEject,
+ B_ID, 128, PciBCtlSync, PciCtlQueryDeviceId,
+ B_UID, 128, PciBCtlSync, PciCtlQueryDeviceUniqueId,
+ B_CAPABILITIES, SIZE_CAP, PciBCtlSync, PciCtlForward, // bugbug
+ B_RES, sizeof(ULONG), PciBCtlSync, PciCtlQueryDeviceResources,
+ B_RES_REQ, sizeof(ULONG), PciBCtlSync, PciCtlQueryDeviceResourceRequirements,
+ B_QUERY_EJECT, SIZE_CALL, PciBCtlSync, PciCtlForward,
+ B_SET_LOCK, sizeof(BOOLEAN), PciBCtlLock, PciCtlLock,
+ B_SET_RESUME, sizeof(BOOLEAN), PciBCtlSync, PciCtlForward,
+ B_SET_POWER, sizeof(POWER_STATE), PciBCtlPower, PciCtlPower,
+ B_SET_RES, 0, PciBCtlSync, PciCtlSetDeviceResources,
+ B_ASSIGN_RES, SIZE_BRES, PciBCtlSync, PciCtlAssignSlotResources,
+ 0, 0, NULL, NULL
+};
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("PAGE")
+#endif
+
+//
+// PciDriverObject - the driver object for pciport.sys
+//
+
+
+PDRIVER_OBJECT PciDriverObject;
+
+//
+// PciCodeLock - Handle for locked code (only used during system
+// Suspend/Hibernate/Resume procedure)
+//
+
+PVOID PciCodeLock;
+
+//
+// PciSuspendRegistration - A registration to the systems
+// Suspend/Hibernate/Resume callback
+//
+
+HAL_CALLBACKS PciHalCallbacks;
+
+//
+// PciSuspendRegistration - A registration to the systems
+// Suspend/Hibernate/Resume callback
+//
+
+PVOID PciSuspendRegistration;
+
+//
+// Some global strings
+//
+
+WCHAR rgzPCIDeviceName[] = L"\\Device\\PciBus_%d";
+WCHAR rgzSuspendCallbackName[] = L"\\Callback\\SuspendHibernateSystem";
+
+WCHAR PCI_ID[] = L"PCI\\%04x_%04x";
+WCHAR PNP_VGA[] = L"PCI\\*PNP_VGA";
+WCHAR PNP_IDE[] = L"PCI\\*PNP_IDE";
diff --git a/private/ntos/nthals/extender/pci/pciport.h b/private/ntos/nthals/extender/pci/pciport.h
new file mode 100644
index 000000000..9e4870ebc
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/pciport.h
@@ -0,0 +1,570 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ pciport.h
+
+Abstract:
+
+ header file for pciport.sys
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "pci.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+//
+// Structures
+//
+
+
+#define PciExtension Reserved[0]
+
+//
+// When queued, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextWorkQueue BusExtenderReserved[0]
+#define ContextControlHandler BusExtenderReserved[2]
+
+//
+// When in progress, the following HAL_DEVICE_CONTROL_CONTEXT values are defined
+//
+
+#define ContextArgument1 BusExtenderReserved[0]
+#define ContextArgument2 BusExtenderReserved[1]
+#define ContextBusyFlag BusExtenderReserved[2]
+
+#define PCIPORTDATA(a) \
+ ((PPCI_PORT) ( ((PPCIBUSDATA) (a)->BusData)->PciExtension))
+
+#define PCI_CONFIG_TYPE(PciData) \
+ ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+#define MAX_VALID_DEVICE_HANDLE 0x7FFFFFFF
+
+// the follow are handle value states when the handle is > MAX_VALID_DEVICE_HANDLE
+#define INITIALIZE_DEVICE_HANDLE 0x80000000
+#define TRANSISTION_DEVICE_HANDLE 0x80000001
+#define INVALID_DEVICE_HANDLE 0x80000002
+
+typedef struct _DEVICE_DATA_ {
+ SINGLE_LIST_ENTRY Next;
+
+ //
+ // SlotNumber for which this device data corrisponds
+ //
+
+ //PCI_SLOT_NUMBER SlotNumber;
+
+ //
+ //
+ //
+
+ BOOLEAN Valid;
+
+ //
+ // DeviceControl in progress flags
+ //
+
+ BOOLEAN SyncBusy;
+ BOOLEAN AsyncBusy;
+
+
+ //
+ // Track the lock state of the device
+ // PendPowerUp is used while an Unlock is in progress
+ // to cause a power up request to wait
+ //
+
+ BOOLEAN Locked;
+ BOOLEAN PendPowerUp;
+
+ //
+ // Track the power state of the device.
+ // If it's powered off, track the device's configuration.
+ //
+ // If the powered off configuration has changed, track the
+ // original configuration in case the new configuration is
+ // not supported by the h/w. (would be a defective device)
+ //
+
+ BOOLEAN Power;
+ PPCI_COMMON_CONFIG CurrentConfig;
+
+ //
+ // Since PCI doesn't have a runtime safe way to determine
+ // the length of it's base register's will we keep track
+ // of them here.
+ //
+
+ ULONG BARBits[PCI_TYPE0_ADDRESSES+1];
+
+ //
+ //
+ //
+
+ BOOLEAN BARBitsSet;
+
+
+ //
+ // Determine if the device's rom base address register should
+ // be enabled
+ //
+
+ BOOLEAN EnableRom;
+
+ //
+ // Flag defective hardware which we've noticed that it's base
+ // address registers do not function properly.
+ //
+
+ BOOLEAN BrokenDevice;
+
+} DEVICE_DATA, *PDEVICE_DATA;
+
+extern POBJECT_TYPE *IoDeviceHandlerObjectType;
+extern PULONG IoDeviceHandlerObjectSize;
+#define DeviceHandler2DeviceData(a) ((PDEVICE_DATA) (((PUCHAR) a) + PcipDeviceHandlerObjectSize))
+#define DeviceData2DeviceHandler(a) ((PDEVICE_HANDLER_OBJECT) (((PUCHAR) a) - PcipDeviceHandlerObjectSize))
+#define DeviceDataSlot(a) DeviceData2DeviceHandler(a)->SlotNumber
+
+typedef struct {
+ BOOLEAN Control;
+} *PBCTL_SET_CONTROL;
+
+typedef struct {
+ PBUS_HANDLER Handler;
+ LIST_ENTRY CheckBus;
+ LIST_ENTRY DeviceControl;
+
+ ULONG NoValidSlots;
+ SINGLE_LIST_ENTRY ValidSlots;
+
+ PVOID Spare;
+} PCI_PORT, *PPCI_PORT;
+
+
+//
+// Internal DeviceControls
+//
+
+#define BCTL_ASSIGN_SLOT_RESOURCES 0x90000001
+#define BCTL_CHECK_DEVICE 0x90000002
+#define BCTL_INITIAL_DEVICE 0x90000003
+
+typedef struct {
+ PUNICODE_STRING RegistryPath;
+ PUNICODE_STRING DriverClassName;
+ PDRIVER_OBJECT DriverObject;
+ PCM_RESOURCE_LIST *AllocatedResources;
+} CTL_ASSIGN_RESOURCES, *PCTL_ASSIGN_RESOURCES;
+
+typedef BOOLEAN (FASTCALL * BGNFNC)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+typedef VOID (* CTLFNC)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+
+typedef struct {
+ ULONG ControlCode;
+ ULONG MinBuffer;
+ BGNFNC BeginDeviceControl;
+ CTLFNC ControlHandler;
+} DEVICE_CONTROL_HANDLER, *PDEVICE_CONTROL_HANDLER;
+
+//
+//
+//
+
+#if DBG
+VOID PciDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+#define DebugPrint(arg) PciDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
+
+//
+// Globals
+//
+
+extern FAST_MUTEX PcipMutex;
+extern KSPIN_LOCK PcipSpinlock;
+extern LIST_ENTRY PcipControlWorkerList;
+extern LIST_ENTRY PcipControlDpcList;
+extern LIST_ENTRY PcipCheckBusList;
+extern ULONG PcipWorkerQueued;
+extern WORK_QUEUE_ITEM PcipWorkItem;
+extern KDPC PcipWorkDpc;
+extern ULONG PcipNextHandle;
+extern DEVICE_CONTROL_HANDLER PcipControl[];
+extern PDRIVER_OBJECT PciDriverObject;
+extern HAL_CALLBACKS PciHalCallbacks;
+extern PVOID PciSuspendRegistration;
+extern PVOID PciCodeLock;
+extern WCHAR rgzPCIDeviceName[];
+extern WCHAR rgzSuspendCallbackName[];
+extern WCHAR PCI_ID[];
+extern WCHAR PNP_VGA[];
+extern WCHAR PNP_IDE[];
+extern BOOLEAN PcipNoBusyFlag;
+extern ULONG PcipDeviceHandlerObjectSize;
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+
+NTSTATUS
+PciPortInitialize (
+ PBUS_HANDLER PciBus
+ );
+
+ULONG
+PcipGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PcipGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PcipSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PcipSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+PcipAssignSlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+NTSTATUS
+PcipQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ );
+
+PDEVICE_HANDLER_OBJECT
+PcipReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber
+ );
+
+NTSTATUS
+PcipDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+NTSTATUS
+PcipHibernateBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+NTSTATUS
+PcipResumeBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ );
+
+VOID
+PcipSuspendNotification (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ );
+
+VOID
+PcipStartWorker (
+ VOID
+ );
+
+VOID
+PcipControlWorker (
+ IN PVOID WorkerContext
+ );
+
+VOID
+PcipControlDpc (
+ PKDPC Dpc,
+ PVOID DeferredContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2
+ );
+
+VOID
+PcipDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlNone (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlSync (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlPower (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceUniqueId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlQueryDeviceResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlSetDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlAssignSlotResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlNone (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PciBCtlResume (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PciCtlForward (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PcipCompletePowerUp (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PcipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData
+ );
+
+VOID
+PcipReadConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData,
+ OUT PPCI_COMMON_CONFIG PciData
+ );
+
+NTSTATUS
+PcipFlushConfig (
+ IN PBUS_HANDLER Handler,
+ IN PDEVICE_DATA DeviceData
+ );
+
+BOOLEAN
+PcipCompareDecodes (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ IN PPCI_COMMON_CONFIG PciData2
+ );
+
+BOOLEAN
+PcipCalcBaseAddrPointers (
+ IN PDEVICE_DATA DeviceData,
+ IN PPCI_COMMON_CONFIG PciData,
+ OUT PULONG *BaseAddress,
+ OUT PULONG NoBaseAddress,
+ OUT PULONG RomIndex
+ );
+
+NTSTATUS
+PcipPowerDownSlot (
+ PBUS_HANDLER Handler,
+ PDEVICE_DATA DeviceData
+ );
+
+VOID
+PciCtlCheckDevice (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+NTSTATUS
+PcipVerifyBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ );
+
+NTSTATUS
+PcipGetBarBits (
+ PDEVICE_DATA DeviceData,
+ PBUS_HANDLER Handler
+ );
+
+PDEVICE_DATA
+PcipFindDeviceData (
+ IN PPCI_PORT PciPort,
+ IN PCI_SLOT_NUMBER SlotNumber
+ );
+
+VOID
+PcipCheckBus (
+ PPCI_PORT PciPort,
+ BOOLEAN Initialize
+ );
+
+BOOLEAN
+PcipCrackBAR (
+ IN PULONG *BaseAddress,
+ IN PULONG BarBits,
+ IN OUT PULONG Index,
+ OUT PLONGLONG pbase,
+ OUT PLONGLONG plength,
+ OUT PLONGLONG pmax
+ );
+
+NTSTATUS
+BugBugSubclass (
+ VOID
+ );
diff --git a/private/ntos/nthals/extender/pci/pciport.rc b/private/ntos/nthals/extender/pci/pciport.rc
new file mode 100644
index 000000000..a9a5fec4b
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/pciport.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "PCI Bus Class Driver"
+#define VER_INTERNALNAME_STR "pciext.sys"
+#define VER_ORIGINALFILENAME_STR "pciext.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pci/port.c b/private/ntos/nthals/extender/pci/port.c
new file mode 100644
index 000000000..e78ba1537
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/port.c
@@ -0,0 +1,713 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ port.c
+
+Abstract:
+
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PcipAssignSlotResources)
+#pragma alloc_text(PAGE,PcipQueryBusSlots)
+#pragma alloc_text(PAGE,PcipHibernateBus)
+#pragma alloc_text(PAGE,PcipResumeBus)
+#pragma alloc_text(PAGE,PcipSuspendNotification)
+#pragma alloc_text(PAGE,PcipReferenceDeviceHandler)
+#endif
+
+
+ULONG
+PcipGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ BusData = (PPCIBUSDATA) BusHandler->BusData;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, sizeof (ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->Pin2Line (BusHandler, RootHandler, SlotNumber, PciData);
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ BusData->ReadConfig (BusHandler, SlotNumber, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+
+ULONG
+PcipGetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ ULONG Status;
+ PDEVICE_DATA DeviceData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ Status = 0;
+ DeviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!DeviceData->Valid) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ return 0;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ if (DataType == 0) {
+
+ //
+ // Type 0 is the same as GetBusData for the slot
+ //
+
+ SlotNumber.u.AsULONG = DeviceHandler->SlotNumber;
+ Status = PcipGetBusData (
+ BusHandler,
+ RootHandler,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+
+ return Status;
+}
+
+
+ULONG
+PcipSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIBUSDATA BusData;
+ ULONG Len, cnt;
+
+ BusData = (PPCIBUSDATA) BusHandler->BusData;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ BusData->ReadConfig (BusHandler, SlotNumber, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->Pin2Line (BusHandler, RootHandler, SlotNumber, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->Line2Pin (BusHandler, RootHandler, SlotNumber, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ BusData->WriteConfig (BusHandler, SlotNumber, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ BusData->WriteConfig (BusHandler, SlotNumber, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+PcipSetDeviceData (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN ULONG DataType,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ ULONG Status;
+ PDEVICE_DATA DeviceData;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ Status = 0;
+ DeviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!DeviceData->Valid) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ return 0;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ if (DataType == 0) {
+
+ //
+ // Type 0 is the same as SetBusData for the slot
+ //
+
+ SlotNumber.u.AsULONG = DeviceHandler->SlotNumber;
+ Status = PcipGetBusData (
+ BusHandler,
+ RootHandler,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+
+ return Status;
+}
+
+
+
+NTSTATUS
+PcipAssignSlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+{
+ CTL_ASSIGN_RESOURCES AssignResources;
+ KEVENT CompletionEvent;
+ ULONG BufferSize;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ NTSTATUS Status;
+
+ PAGED_CODE ();
+
+ //
+ // Foreward this request through a DeviceControl such that it
+ // gets the proper synchronzation on the device
+ //
+
+ DeviceHandler = BusHandler->ReferenceDeviceHandler (
+ BusHandler,
+ BusHandler,
+ SlotNumber
+ );
+
+ if (!DeviceHandler) {
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ AssignResources.RegistryPath = RegistryPath;
+ AssignResources.DriverClassName = DriverClassName;
+ AssignResources.DriverObject = DriverObject;
+ AssignResources.AllocatedResources = AllocatedResources;
+ BufferSize = sizeof (AssignResources);
+
+ //
+ // Make synchrous DeviceControl request
+ //
+
+ Status = HalDeviceControl (
+ DeviceHandler,
+ DeviceObject,
+ BCTL_ASSIGN_SLOT_RESOURCES,
+ &AssignResources,
+ &BufferSize,
+ NULL,
+ NULL
+ );
+
+ //
+ // Free the reference to DeviceHandler
+ //
+
+ ObDereferenceObject (DeviceHandler);
+
+ //
+ // Done
+ //
+
+ return Status;
+}
+
+
+NTSTATUS
+PcipQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+{
+ PSINGLE_LIST_ENTRY Link;
+ PPCI_PORT PciPort;
+ PDEVICE_DATA DeviceData;
+ ULONG cnt;
+
+ PAGED_CODE ();
+
+ PciPort = PCIPORTDATA (BusHandler);
+
+ //
+ // Synchronize will new devices being added
+ //
+
+ ExAcquireFastMutex (&PcipMutex);
+
+ //
+ // Fill in returned buffer length, or what size buffer is needed
+ //
+
+
+ *ReturnedLength = PciPort->NoValidSlots * sizeof (ULONG);
+ if (BufferSize < *ReturnedLength) {
+
+ //
+ // Callers buffer is not large enough
+ //
+
+ ExReleaseFastMutex (&PcipMutex);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Return caller all the possible slot number
+ //
+
+ cnt = 0;
+ for (Link = PciPort->ValidSlots.Next; Link; Link = Link->Next) {
+ DeviceData = CONTAINING_RECORD (Link, DEVICE_DATA, Next);
+ if (DeviceData->Valid) {
+ cnt += 1;
+ *(SlotNumbers++) = DeviceDataSlot(DeviceData);
+ }
+ }
+
+ *ReturnedLength = cnt * sizeof (ULONG);
+ ExReleaseFastMutex (&PcipMutex);
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+PcipDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+{
+ ULONG i;
+ ULONG ControlCode;
+ ULONG Junk;
+ PULONG BufferLength;
+ PLIST_ENTRY OldTail;
+ BOOLEAN UseWorker;
+
+ for (i=0; PcipControl[i].ControlHandler; i++) {
+ if (PcipControl[i].ControlCode == Context->DeviceControl.ControlCode) {
+
+ //
+ // Found DeviceControl handler
+ //
+
+ Context->ContextControlHandler = (ULONG) (PcipControl + i);
+
+ //
+ // Verify callers buffer is the min required length
+ //
+
+
+ if (*Context->DeviceControl.BufferLength < PcipControl[i].MinBuffer) {
+ Context->DeviceControl.Status = STATUS_BUFFER_TOO_SMALL;
+ *Context->DeviceControl.BufferLength = PcipControl[i].MinBuffer;
+ HalCompleteDeviceControl (Context);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ if (KeGetCurrentIrql() < DISPATCH_LEVEL ||
+ (Context->DeviceControl.ControlCode == BCTL_SET_POWER &&
+ *((PPOWER_STATE) Context->DeviceControl.Buffer) == PowerUp)){
+
+ //
+ // All slot controls, expect a power up request, may touch
+ // paged code or data. If the current irql is low enough or
+ // this is a power up go dispatch now; otherwise, queue the
+ // request to a worker thread.
+ //
+
+ PcipDispatchControl (Context);
+
+ } else {
+
+ //
+ // Enqueue to worker thread
+ //
+
+ ExInterlockedInsertTailList (
+ &PcipControlWorkerList,
+ (PLIST_ENTRY) &Context->ContextWorkQueue,
+ &PcipSpinlock
+ );
+
+ //
+ // Make sure worker is requested
+ //
+
+ PcipStartWorker ();
+ }
+
+
+ return STATUS_PENDING;
+ }
+ }
+
+ //
+ // Unkown control code
+ //
+
+ return STATUS_INVALID_PARAMETER;
+}
+
+PDEVICE_HANDLER_OBJECT
+PcipReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber
+ )
+{
+ PDEVICE_DATA DeviceData;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ PPCI_PORT PciPort;
+ NTSTATUS Status;
+
+ PAGED_CODE ();
+
+ ExAcquireFastMutex (&PcipMutex);
+
+ PciPort = PCIPORTDATA(BusHandler);
+ DeviceData = PcipFindDeviceData (PciPort, SlotNumber);
+ DeviceHandler = NULL;
+ if (DeviceData) {
+ DeviceHandler = DeviceData2DeviceHandler (DeviceData);
+ Status = ObReferenceObjectByPointer(
+ DeviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ DeviceHandler = NULL;
+ }
+ }
+
+ ExReleaseFastMutex (&PcipMutex);
+ return DeviceHandler;
+}
+
+
+
+NTSTATUS
+PcipHibernateBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ )
+{
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+
+
+NTSTATUS
+PcipResumeBus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler
+ )
+{
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+VOID
+PcipSuspendNotification (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ PAGED_CODE();
+
+ switch ((ULONG) Argument1) {
+ case 0:
+ //
+ // Lock code down which might be needed to perform a suspend
+ //
+
+ ASSERT (PciCodeLock == NULL);
+ PciCodeLock = MmLockPagableCodeSection (&PcipHibernateBus);
+ break;
+
+ case 1:
+ //
+ // Release the code lock
+ //
+
+ MmUnlockPagableImageSection (PciCodeLock);
+ PciCodeLock = NULL;
+ break;
+ }
+}
diff --git a/private/ntos/nthals/extender/pci/sources b/private/ntos/nthals/extender/pci/sources
new file mode 100644
index 000000000..4f5a2e927
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=dd
+
+TARGETNAME=pciport
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=pciport.rc \
+ pcidata.c \
+ bus.c \
+ control.c \
+ devres.c \
+ init.c \
+ misc.c \
+ port.c
+
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=