summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/extender
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/extender')
-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
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/bus.c886
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/busdata.c902
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/busp.h499
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/control.c725
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/data.c159
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/init.c482
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/misc.c471
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbapi.h235
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c1562
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbios.h241
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm89
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/pbiosc.c773
-rw-r--r--private/ntos/nthals/extender/pnpbios/i386/resource.c367
-rw-r--r--private/ntos/nthals/extender/pnpbios/makefile6
-rw-r--r--private/ntos/nthals/extender/pnpbios/pnpbios.rc11
-rw-r--r--private/ntos/nthals/extender/pnpbios/sources49
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/bus.c962
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/busp.h473
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/convert.c1092
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/data.c58
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/init.c620
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/isolate.c1607
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/makefile6
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/misc.c1258
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/pbios.h241
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/pnpisa.h164
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/pnpisa.rc11
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/resource.c680
-rw-r--r--private/ntos/nthals/extender/pnpisa.sur/sources47
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/bus.c1036
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/busp.h576
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/control.c511
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/convert.c1077
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/data.c156
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/init.c506
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/isolate.c1574
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/misc.c626
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/pnpisa.h155
-rw-r--r--private/ntos/nthals/extender/pnpisa/i386/resource.c555
-rw-r--r--private/ntos/nthals/extender/pnpisa/makefile6
-rw-r--r--private/ntos/nthals/extender/pnpisa/pnpisa.rc11
-rw-r--r--private/ntos/nthals/extender/pnpisa/sources48
53 files changed, 26356 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=
diff --git a/private/ntos/nthals/extender/pnpbios/i386/bus.c b/private/ntos/nthals/extender/pnpbios/i386/bus.c
new file mode 100644
index 000000000..b002bf1cf
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/bus.c
@@ -0,0 +1,886 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ port.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) May-20-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+VOID
+MbpInvalidateSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ );
+
+VOID
+MbpDeleteSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,MbQueryBusSlots)
+#pragma alloc_text(PAGE,MbpCheckBus)
+#pragma alloc_text(PAGE,MbpReferenceDeviceHandler)
+#endif
+
+
+ULONG
+MbGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+MbSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function sets the Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to be set.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+MbGetDeviceData (
+ 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
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ ULONG dataLength;
+ PDEVICE_DATA deviceData;
+
+ UNREFERENCED_PARAMETER ( DataType);
+
+ dataLength = 0;
+ deviceData = DeviceHandler2DeviceData (DeviceHandler);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!(deviceData->Flags & DEVICE_FLAGS_VALID)) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ return dataLength;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ //
+ // Synchronize with other pnp bios service functions.
+ //
+
+ ExAcquireFastMutex(&MbpMutex);
+
+ dataLength = deviceData->BusDataLength;
+ if (Offset < dataLength) {
+ dataLength -= Offset;
+ if (dataLength > Length) {
+ dataLength = Length;
+ }
+ RtlMoveMemory(Buffer, (PUCHAR)deviceData->BusData + Offset, dataLength);
+ } else {
+ dataLength = 0;
+ }
+
+ ExReleaseFastMutex(&MbpMutex);
+ return dataLength;
+}
+
+ULONG
+MbSetDeviceData (
+ 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
+ )
+/*++
+
+Routine Description:
+
+ The function sets Pnp Bios data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data set.
+
+--*/
+{
+ //
+ // We don't let drivers change Pnp device data.
+ //
+
+ return 0;
+}
+
+NTSTATUS
+MbQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns a list of currently available SlotNumber.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ SlotNumber - Supplies a variable to receives the number of available slots.
+
+ Length - Supplies a count in bytes of the stored data. If this function
+ returns STATUS_BUFFER_TOO_SMALL, this variable supplies the required
+ size.
+
+Return Value:
+
+ STATUS_BUFFER_TOO_SMALL if caller supplied buffer is not big enough.
+
+--*/
+
+{
+ PMB_BUS_EXTENSION busExtension;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_DATA deviceData;
+ ULONG count = 0;
+
+ PAGED_CODE ();
+
+ busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
+
+ //
+ // Synchronize with other pnp bios device handle assignment.
+ //
+
+ ExAcquireFastMutex(&MbpMutex);
+
+ //
+ // Fill in returned buffer length, or what size buffer is needed
+ //
+
+
+ *ReturnedLength = busExtension->NoValidSlots * sizeof (ULONG);
+ if (BufferSize < *ReturnedLength) {
+
+ //
+ // Callers buffer is not large enough
+ //
+
+ ExReleaseFastMutex (&MbpMutex);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Return caller all the possible slot number
+ //
+
+ for (link = busExtension->ValidSlots.Next; link; link = link->Next) {
+ deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
+ if (deviceData->Flags & DEVICE_FLAGS_VALID) {
+ *SlotNumbers = DeviceDataSlot(deviceData);
+ SlotNumbers++;
+ count += 1;
+ }
+ }
+
+ *ReturnedLength = count * sizeof (ULONG);
+ ExReleaseFastMutex (&MbpMutex);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ The function is the bus handler specific verion of HalDeviceControl.
+
+Arguments:
+
+ Context - The DeviceControl context. The context has all the information
+ for the HalDeviceControl operation being performed.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ ULONG i, junk;
+ ULONG controlCode;
+ PULONG bufferLength;
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ for (i = 0; i < NUMBER_DEVICE_CONTROL_FUNCTIONS; i++) {
+
+ if (MbpDeviceControl[i].ControlCode == Context->DeviceControl.ControlCode) {
+ if (MbpDeviceControl[i].ControlHandler == NULL) {
+ Context->DeviceControl.Status = STATUS_NOT_IMPLEMENTED;
+ status = STATUS_NOT_IMPLEMENTED;
+ goto deviceControlDone;
+ }
+
+ //
+ // Found DeviceControl handler
+ //
+
+ Context->ContextControlHandler = (ULONG)(MbpDeviceControl + i);
+
+ //
+ // Verify callers buffer is the min required length
+ //
+
+ if (*Context->DeviceControl.BufferLength < MbpDeviceControl[i].MinBuffer) {
+ Context->DeviceControl.Status = STATUS_BUFFER_TOO_SMALL;
+ *Context->DeviceControl.BufferLength = MbpDeviceControl[i].MinBuffer;
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto deviceControlDone;
+ }
+
+ if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
+
+ //
+ // All supported slot control functions touch paged code or data.
+ // If the current irql is low enough go dispatch now; otherwise,
+ // queue the request to a worker thread.
+ //
+
+ MbpDispatchControl (Context);
+
+ } else {
+
+ //
+ // Enqueue to worker thread
+ //
+
+ ExInterlockedInsertTailList (
+ &MbpControlWorkerList,
+ (PLIST_ENTRY) &Context->ContextWorkQueue,
+ &MbpSpinlock
+ );
+
+ //
+ // Make sure worker is requested
+ //
+
+ MbpStartWorker ();
+ }
+ return STATUS_PENDING;
+ }
+ }
+
+deviceControlDone:
+ HalCompleteDeviceControl (Context);
+ return status;
+}
+
+VOID
+MbpCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+
+/*++
+
+Routine Description:
+
+ The function reenumerates the bus specified by BusHandler.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the BusHandler of the bus to be enumerated.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG slotNumber, nextSlotNumber;
+ BOOLEAN dockConnector;
+ PDEVICE_DATA deviceData;
+ PPNP_BIOS_DEVICE_NODE busData;
+ PMB_BUS_EXTENSION busExtension;
+ ULONG length, noSlots;
+ NTSTATUS status;
+ PHAL_SYSTEM_DOCK_INFORMATION dockInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ ULONG objectSize;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ BOOLEAN notifyBusCheck;
+
+ PAGED_CODE();
+
+ busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
+ notifyBusCheck = FALSE;
+
+ //
+ // We may be removing references to this bus handler, so add
+ // a reference now
+ //
+
+ HalReferenceBusHandler (BusHandler);
+
+ //
+ // Acquire fast mutex to access device data
+ //
+
+ ExAcquireFastMutex (&MbpMutex);
+ MbpInvalidateSlots(busExtension);
+
+ //
+ // Check the bus for new devices
+ //
+
+ nextSlotNumber = 0;
+ while (nextSlotNumber != (ULONG) -1) {
+ slotNumber = nextSlotNumber;
+ status = MbpGetBusData(BusHandler->BusNumber,
+ &nextSlotNumber,
+ &busData,
+ &length,
+ &dockConnector);
+ if (NT_SUCCESS(status)) {
+ deviceData = MbpFindDeviceData (busExtension, slotNumber);
+ if (deviceData == NULL ||
+ length != deviceData->BusDataLength ||
+ RtlCompareMemory(busData, deviceData->BusData, length) != length) {
+
+ notifyBusCheck = TRUE;
+
+ //
+ // if Not found - this is a newly added device or
+ // if devicedata exists already, make sure its busdata is not changed.
+ // Otherwise, we assign a new handler to this slot. This invalidate
+ // the access to the old bus data.
+ //
+
+ //
+ // Initialize the object attributes that will be used to create the
+ // Device Handler Object.
+ //
+
+ InitializeObjectAttributes(
+ &objectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+
+ objectSize = MbpDeviceHandlerObjectSize + 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;
+ if (dockConnector) {
+ deviceHandler->SlotNumber = DOCK_VIRTUAL_SLOT_NUMBER;
+ } else {
+ deviceHandler->SlotNumber = slotNumber;
+ }
+
+ //
+ // 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. Skip this slot.
+ //
+
+ continue;
+ }
+
+ ZwClose (handle);
+
+ //
+ // Intialize device tracking structure
+ //
+
+ deviceHandler->BusHandler = BusHandler;
+ HalReferenceBusHandler(BusHandler);
+
+ deviceData = DeviceHandler2DeviceData(deviceHandler);
+ deviceData->BusData = busData;
+ deviceData->BusDataLength = length;
+ deviceData->Flags |= DEVICE_FLAGS_VALID;
+
+ DebugPrint ((DEBUG_MESSAGE, "PnpBios: adding slot %x\n", DeviceDataSlot(deviceData)));
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ busExtension->NoValidSlots += 1;
+ ExInterlockedPushEntryList (
+ &busExtension->ValidSlots,
+ &deviceData->Next,
+ &MbpSpinlock
+ );
+ } else {
+ ExFreePool(busData);
+ deviceData->Flags |= DEVICE_FLAGS_VALID;
+ }
+
+ //
+ // If this is the docking station slot, remember it.
+ //
+
+ if (dockConnector) {
+ busExtension->DockingStationDevice = deviceData;
+ deviceData->Flags |= DEVICE_FLAGS_DOCKING_STATION;
+ }
+ }
+ }
+
+ //
+ // Go through the slot data link list to delete all the removed slots.
+ //
+
+ noSlots = busExtension->NoValidSlots;
+ MbpDeleteSlots(busExtension);
+ if (noSlots != busExtension->NoValidSlots) {
+ notifyBusCheck = TRUE;
+ }
+ ExReleaseFastMutex (&MbpMutex);
+
+ //
+ // If this is top level pnp bios bus we will determine docking station information
+ // and all Hal to set dock information.
+ //
+
+ if (BusHandler->BusNumber == MbpBusNumber[0] &&
+ NT_SUCCESS(MbpGetDockInformation(&dockInfo, &length)) ) {
+ HalSetSystemInformation(HalSystemDockInformation, length, dockInfo);
+ ExFreePool(dockInfo);
+ }
+
+ //
+ // Undo reference to bus handler from top of function
+ //
+
+ HalDereferenceBusHandler (BusHandler);
+
+ //
+ // Do we need to notify the system buscheck callback?
+ //
+
+ if (notifyBusCheck) {
+ HAL_BUS_INFORMATION busInfo;
+
+ busInfo.BusType = BusHandler->InterfaceType;
+ busInfo.ConfigurationType = BusHandler->ConfigurationType;
+ busInfo.BusNumber = BusHandler->BusNumber;
+ busInfo.Reserved = 0;
+ ExNotifyCallback (
+ MbpHalCallbacks.BusCheck,
+ &busInfo,
+ (PVOID)BusHandler->BusNumber
+ );
+ }
+}
+
+PDEVICE_HANDLER_OBJECT
+MbpReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function returns a reference to the devce handler specified by SlotNumber
+ and BusHandler.
+
+Arguments:
+
+ BusHandler -
+
+ RootHanler -
+
+ SlotNumber -
+
+Return Value:
+
+ a reference to DEVICE_HANDLER_OBJECT.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PMB_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+
+ PAGED_CODE ();
+
+ ExAcquireFastMutex (&MbpMutex);
+
+ busExtension = (PMB_BUS_EXTENSION)BusHandler->BusData;
+ deviceData = MbpFindDeviceData (busExtension, 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 (&MbpMutex);
+ return deviceHandler;
+}
+
+PDEVICE_DATA
+MbpFindDeviceData (
+ IN PMB_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list to find the desired SlotNumber's
+ device data. The caller must hold the MbpMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to current bus'es extension.
+
+ SlotNumber - specified the desired device data. -1 means docking station device data.
+
+Return Value:
+
+ A pointer to the DEVICE_DATA if found. Otherwise a value of NULL is returned.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ //
+ // Go through the slot data link list to find a match.
+ //
+
+ if (SlotNumber == DOCK_VIRTUAL_SLOT_NUMBER) {
+ return BusExtension->DockingStationDevice;
+ } else {
+ for (link = BusExtension->ValidSlots.Next; link; link = link->Next) {
+ deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
+ if (DeviceDataSlot(deviceData) == SlotNumber) {
+ break;
+ }
+ }
+ }
+
+ if (!link) {
+ return NULL;
+ } else {
+ return deviceData;
+ }
+}
+
+VOID
+MbpInvalidateSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list and marks all the devices as invalid.
+ The caller must acquire MbpMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PSINGLE_LIST_ENTRY link;
+
+ //
+ // Go through the slot data link list to mark ALL the slots as
+ // in transition state.
+ //
+
+ for (link = BusExtension->ValidSlots.Next; link; link = link->Next) {
+ deviceData = CONTAINING_RECORD (link, DEVICE_DATA, Next);
+ deviceData->Flags &= ~DEVICE_FLAGS_VALID;
+ }
+
+ //
+ // Invalidate the docking station slot pointer
+ //
+
+ BusExtension->DockingStationDevice = NULL;
+ BusExtension->DockingStationId = UNKNOWN_DOCKING_IDENTIFIER;
+ BusExtension->DockingStationSerialNumber = 0;
+}
+
+VOID
+MbpDeleteSlots (
+ IN PMB_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list and deletes all the invalid
+ slots/devices.
+ Note the MbpMutex must be acquired before calling this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PSINGLE_LIST_ENTRY *link;
+
+ //
+ // Go through the slot data link list to free all the slot
+ // marked as invalid.
+ //
+
+ link = &BusExtension->ValidSlots.Next;
+ while (*link) {
+ deviceData = CONTAINING_RECORD (*link, DEVICE_DATA, Next);
+ if (!(deviceData->Flags & DEVICE_FLAGS_VALID)) {
+ DebugPrint((DEBUG_MESSAGE, "Remove slot %x\n", DeviceDataSlot(deviceData)));
+
+ //
+ // In theory I should deallocate the BusData only when the ref count of the
+ // deviceData down to zero and deallocated. Here I am safe to do so because
+ // the DeviceDispatchContol routine checks the DeviceData flag is valid before
+ // reference the BusData.
+ //
+
+ if (deviceData->BusData) {
+ ExFreePool(deviceData->BusData);
+ }
+ *link = (*link)->Next;
+ deviceHandler = DeviceData2DeviceHandler(deviceData);
+ ObDereferenceObject (deviceHandler);
+ HalDereferenceBusHandler (BusExtension->BusHandler);
+ BusExtension->NoValidSlots--;
+ } else {
+ link = &((*link)->Next);
+ }
+ }
+}
+
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/busdata.c b/private/ntos/nthals/extender/pnpbios/i386/busdata.c
new file mode 100644
index 000000000..58dded523
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/busdata.c
@@ -0,0 +1,902 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busdata.c
+
+Abstract:
+
+ This module contains code to query/set pnp bios slot data.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-25-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+PUCHAR
+MbpFindNextPnpEndTag (
+ IN PUCHAR BusData,
+ IN LONG Limit
+ );
+
+#pragma alloc_text(PAGE,MbpGetBusData)
+#pragma alloc_text(PAGE,MbpGetCompatibleDeviceId)
+#pragma alloc_text(PAGE,MbpGetSlotResources)
+#pragma alloc_text(PAGE,MbpGetSlotResourceRequirements)
+#pragma alloc_text(PAGE,MbpSetSlotResources)
+#pragma alloc_text(PAGE,MbpFindNextPnpEndTag)
+
+NTSTATUS
+MbpGetBusData (
+ ULONG BusNumber,
+ PULONG SlotNumber,
+ PVOID *BusData,
+ PULONG Length,
+ PBOOLEAN DockingSlot
+ )
+/*++
+
+Routine Description:
+
+ This function returns the pnp bios bus data to the caller.
+ Caller is responsible to release the data buffer. No mater what the returned
+ status is, this routine always returns a valid next slot number.
+
+Arguments:
+
+ BusNumber - specifies the desired bus.
+
+ SlotNumber - specifies a variable to indicate the slot whoes data is desired and
+ to receive the next slot number (-1 if no more slot.)
+
+ BusData - supplies a variable to receive the data buffer pointer.
+
+ Length - supplies a variable to receive the length of the data buffer
+
+ DockingSlot - supplies a variable to receive if the slot is a docking station slot.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status;
+ PPNP_BIOS_DEVICE_NODE busData;
+ PUCHAR p, source;
+ ULONG size, bufferSize, nextSlot = 0;
+ USHORT junk;
+ PB_PARAMETERS biosParameters;
+
+ PAGED_CODE();
+
+ //
+ // If registry data is availble, we will get it from registry data.
+ // Note, the registry data is available at init time only.
+ //
+
+ source = NULL;
+ *DockingSlot = FALSE;
+ if (PbBiosRegistryData) {
+
+ //
+ // First skip Pnp Bios installation check data
+ //
+
+ p = (PUCHAR)(PbBiosRegistryData + 1);
+ size = ((PKEY_VALUE_FULL_INFORMATION)PbBiosKeyInformation)->DataLength;
+ size -= sizeof(PNP_BIOS_INSTALLATION_CHECK) + sizeof(CM_PARTIAL_RESOURCE_LIST);
+ while (size >= sizeof(PNP_BIOS_DEVICE_NODE)) {
+ if (*SlotNumber == ((PPNP_BIOS_DEVICE_NODE)p)->Node) {
+
+ //
+ // Find the desired slot data, determine next slot and
+ // do some more checks.
+ //
+
+ bufferSize = ((PPNP_BIOS_DEVICE_NODE)p)->Size;
+ size -= bufferSize;
+ if (size >= sizeof(PNP_BIOS_DEVICE_NODE)) {
+ nextSlot = ((PPNP_BIOS_DEVICE_NODE)(p + bufferSize))->Node;
+ } else {
+ nextSlot = (ULONG) -1;
+ }
+
+ if (((PPNP_BIOS_DEVICE_NODE)p)->DeviceType[0] == BASE_TYPE_DOCKING_STATION) {
+ if (BusNumber == MbpBusNumber[0]) {
+
+ //
+ // If this is a docking station slot and the target BusNumber is the first bus,
+ // return the data and indicate this is a docking station slot.
+ //
+
+ *DockingSlot = TRUE;
+ source = p;
+ }
+ break;
+ }
+
+ //
+ // If this is a device in the deocking station, it can only belong to BusNumber 1
+ // If this is a device in the system board, it can only belong to BusNumber 0
+ //
+
+ if (((PPNP_BIOS_DEVICE_NODE)p)->DeviceAttributes & DEVICE_DOCKING) {
+ if (BusNumber == MbpBusNumber[1]) {
+ source = p;
+ }
+ } else if (BusNumber == MbpBusNumber[0]) {
+ source = p;
+ }
+ break;
+ }
+ size -= ((PPNP_BIOS_DEVICE_NODE)p)->Size;
+ p = p + ((PPNP_BIOS_DEVICE_NODE)p)->Size;
+ }
+
+ if (!source) {
+ if (*SlotNumber == 0) {
+ p = (PUCHAR)(PbBiosRegistryData + 1);
+ *SlotNumber = ((PPNP_BIOS_DEVICE_NODE)p)->Node;
+ } else {
+ *SlotNumber = nextSlot;
+ }
+ return STATUS_NO_SUCH_DEVICE;
+ }
+ } else {
+
+ //
+ // Registry data is not available. Call pnp bios or hardware to
+ // get the max buffer size if necessary.
+ //
+
+ if (MbpMaxDeviceData == 0) {
+ biosParameters.Function = PNP_BIOS_GET_NUMBER_DEVICE_NODES;
+ biosParameters.u.GetNumberDeviceNodes.NumberNodes = &junk;
+ biosParameters.u.GetNumberDeviceNodes.NodeSize = (PUSHORT)&MbpMaxDeviceData;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_BREAK, "GetBusData: calling BIOS GET_NUMBER_NODES failed.\n"));
+ *SlotNumber = 0;
+ return STATUS_NO_SUCH_DEVICE;
+ } else {
+ bufferSize = MbpMaxDeviceData;
+ }
+ }
+ }
+
+ //
+ // Allocate space to return the slot data
+ //
+
+ busData = (PPNP_BIOS_DEVICE_NODE) ExAllocatePoolWithTag (
+ PagedPool, bufferSize, 'bPnP');
+
+ if (busData == NULL) {
+
+ //
+ // Leave Slot unchanged, so it wil be the next slot number to try. This gives
+ // us another chance to retry the operation.
+ //
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // If the data is available already copy it to data buffer and return.
+ //
+
+ if (source) {
+ RtlMoveMemory(busData, source, bufferSize);
+ *SlotNumber = nextSlot;
+ *BusData = busData;
+ *Length = busData->Size;
+ } else {
+
+ //
+ // Else we need to resort to Pnp Bios runtime API or hardware ...
+ //
+
+ nextSlot = *SlotNumber;
+ biosParameters.Function = PNP_BIOS_GET_DEVICE_NODE;
+ biosParameters.u.GetDeviceNode.NodeBuffer = busData;
+ biosParameters.u.GetDeviceNode.Node = (PUSHORT)&nextSlot;
+ biosParameters.u.GetDeviceNode.Control = GET_CURRENT_CONFIGURATION;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ *SlotNumber = 0;
+ ExFreePool(busData);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ if (nextSlot == 0xFF) {
+ nextSlot = (ULONG) -1;
+ }
+
+ //
+ // Make sure the slot matches the bus number.
+ //
+
+ if (*SlotNumber != (ULONG)busData->Node) {
+
+ //
+ // This happens when *SlotNumber == 0. In this case, bios
+ // gives us the first valid slot data.
+ //
+
+ *SlotNumber = (ULONG)busData->Node;
+ return STATUS_NO_SUCH_DEVICE;
+ } else {
+ *SlotNumber = nextSlot;
+ }
+ if ((busData->DeviceType[0] == BASE_TYPE_DOCKING_STATION && BusNumber != MbpBusNumber[0]) ||
+ (busData->DeviceAttributes & DEVICE_DOCKING && BusNumber == MbpBusNumber[0]) ||
+ (!(busData->DeviceAttributes & DEVICE_DOCKING) && BusNumber == MbpBusNumber[1]) ) {
+ ExFreePool(busData);
+ return STATUS_NO_SUCH_DEVICE;
+ } else {
+ *BusData = busData;
+ *Length = busData->Size;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbpGetCompatibleDeviceId (
+ PVOID BusData,
+ ULONG IdIndex,
+ PWCHAR Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp bios id for the specified Busdata
+ and Id index. If Id index = 0, the Hardware ID will be return; if id
+ index = n, the Nth compatible id will be returned.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ IdIndex - supplies the index of the compatible id desired.
+
+ Buffer - supplies a pointer to a buffer to the compatible Id. Caller must
+ make sure the buffer is big enough.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p, end;
+ UCHAR tag;
+ ULONG count = 0;
+ LONG size;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ ULONG id;
+
+ PAGED_CODE();
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
+ if (IdIndex == 0) {
+
+ //
+ // Caller is asking for hardware id
+ //
+
+ id = slotData->ProductId;
+ } else {
+
+ //
+ // caller is asking for compatible id
+ //
+
+ IdIndex--;
+ p = (PUCHAR)(slotData + 1);
+ size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
+ end = p + size;
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
+ if (!p) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ p += 2;
+ p = MbpFindNextPnpEndTag(p, (LONG)(end - p)); // skip possible resources
+ if (!p) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ p += 2;
+ status = STATUS_NO_MORE_ENTRIES;
+ while ((tag = *p) != TAG_COMPLETE_END) {
+ ASSERT (tag == TAG_COMPLETE_COMPATIBLE_ID);
+ if (count == IdIndex) {
+ id = *(PULONG)(p + 1);
+ status = STATUS_SUCCESS;
+ break;
+ } else {
+ count++;
+ }
+
+ //
+ // Advance to next compatible id.
+ //
+
+ p += (TAG_COMPLETE_COMPATIBLE_ID & SMALL_TAG_SIZE_MASK) + 1;
+ }
+ }
+
+ if (NT_SUCCESS(status)) {
+ PbDecompressEisaId(id, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ swprintf(Buffer, L"BIOS\\*%s", unicodeString.Buffer);
+ RtlFreeUnicodeString(&unicodeString);
+ }
+ return status;
+}
+
+NTSTATUS
+MbpGetSlotResources (
+ IN ULONG BusNumber,
+ IN PVOID BusData,
+ IN OUT PCM_RESOURCE_LIST *CmResources,
+ OUT PULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp bios slot/device resource in CM
+ format. Caller is responsible to free the resource buffer.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ CmResources - supplies a variable to receive the returned resource list.
+
+ Length - supplies a variable to receive the length of the data buffer
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
+ p = (PUCHAR)(slotData + 1);
+ status = PbBiosResourcesToNtResources (
+ BusNumber,
+ slotData->Node,
+ &p,
+ PB_CM_FORMAT,
+ (PUCHAR *) CmResources,
+ Length
+ );
+ return status;
+}
+
+NTSTATUS
+MbpGetSlotResourceRequirements (
+ ULONG BusNumber,
+ PVOID BusData,
+ PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ PULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp bios slot/device resource in IO
+ format. Caller is responsible to free the resource buffer.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ IoResources - supplies a variable to receive the returned resource requirements list.
+
+ Length - supplies a variable to receive the length of the data buffer
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p;
+ LONG size;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ *IoResources = NULL;
+ *Length = 0;
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)BusData;
+ p = (PUCHAR)(slotData + 1);
+ size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
+
+ //
+ // Skip allocated resource descriptors
+ //
+
+ p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
+ if (p) {
+ p += 2;
+ status = PbBiosResourcesToNtResources (
+ BusNumber,
+ slotData->Node,
+ &p,
+ PB_IO_FORMAT,
+ (PUCHAR *)IoResources,
+ Length
+ );
+ }
+ return status;
+}
+
+NTSTATUS
+MbpSetSlotResources (
+ PVOID *BusData,
+ PCM_RESOURCE_LIST CmResources,
+ ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function sets the caller specified resource to pnp bios slot/device
+ data.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios slot/device data.
+
+ CmResources - supplies a variable to receive the returned resource list.
+
+ Length - supplies the length of the resource data
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status;
+ PPNP_BIOS_DEVICE_NODE slotData;
+ PUCHAR p, pEnd, src, requirements;
+ PUCHAR biosResources;
+ ULONG biosResourceSize, totalSize;
+ LONG size;
+ PB_PARAMETERS biosParameters;
+
+ PAGED_CODE();
+
+ slotData = (PPNP_BIOS_DEVICE_NODE)(*BusData);
+ p = (PUCHAR)(slotData + 1);
+ size = slotData->Size - sizeof(PNP_BIOS_DEVICE_NODE);
+ pEnd = p + size;
+
+ //
+ // Skip allocated resource descriptors to find requirements list
+ //
+
+ p = MbpFindNextPnpEndTag(p, size); // skip allocated resources
+ if (!p) {
+ DebugPrint((DEBUG_BREAK, "SetResource:Could not find allocated resource END tag\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ p += 2;
+ requirements = p;
+ size = (ULONG)pEnd - (ULONG)p;
+
+ status = PbCmResourcesToBiosResources (
+ CmResources,
+ requirements,
+ &biosResources,
+ &biosResourceSize
+ );
+ if (NT_SUCCESS(status)) {
+ p = ExAllocatePoolWithTag(
+ PagedPool,
+ size + sizeof(PNP_BIOS_DEVICE_NODE) + biosResourceSize,
+ 'bPnP');
+ if (!p) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(p, slotData, sizeof(PNP_BIOS_DEVICE_NODE));
+ slotData = (PPNP_BIOS_DEVICE_NODE)p;
+ p += sizeof(PNP_BIOS_DEVICE_NODE);
+ RtlMoveMemory(p, biosResources, biosResourceSize);
+ p += biosResourceSize;
+ RtlMoveMemory(p, requirements, size);
+ totalSize = size + sizeof(PNP_BIOS_DEVICE_NODE) + biosResourceSize;
+ slotData->Size = (USHORT)totalSize;
+
+ //
+ // call Pnp Bios to set the resources
+ //
+
+ biosParameters.Function = PNP_BIOS_SET_DEVICE_NODE;
+ biosParameters.u.SetDeviceNode.Node = slotData->Node;
+ biosParameters.u.SetDeviceNode.NodeBuffer = slotData;
+ biosParameters.u.SetDeviceNode.Control = SET_CONFIGURATION_NOW;
+ status = PbHardwareService (&biosParameters);
+ if (NT_SUCCESS(status)) {
+
+ //
+ // Update slotdat pointer
+ //
+
+ ExFreePool(*BusData);
+ *BusData = slotData;
+ } else {
+ ExFreePool(slotData);
+ }
+ }
+ }
+ return status;
+}
+
+NTSTATUS
+MbpGetDockInformation (
+ OUT PHAL_SYSTEM_DOCK_INFORMATION *DockInfo,
+ PULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function returns the docking station Id and serial number.
+ Caller must free the Buffer.
+
+Arguments:
+
+ DockInfo - supplies a pointer to a variable to receive the dock information.
+
+ Length - supplies a pointer to a variable to receive the length of the information.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PB_DOCKING_STATION_INFORMATION biosDockInfo;
+ PB_PARAMETERS biosParameters;
+ NTSTATUS status;
+ PUNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ PHAL_SYSTEM_DOCK_INFORMATION dock;
+ ULONG dockIdLength = 0, serialLength = 0;
+ USHORT dockState;
+
+ PAGED_CODE();
+
+ //
+ // Invoke pnp bios to get docking station information
+ //
+
+ biosParameters.Function = PNP_BIOS_GET_DOCK_INFORMATION;
+ biosParameters.u.GetDockInfo.DockingStationInfo = &biosDockInfo;
+ biosParameters.u.GetDockInfo.DockState = &dockState;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Allocate memory to return dock information
+ //
+
+ dock = (PHAL_SYSTEM_DOCK_INFORMATION)ExAllocatePool (
+ PagedPool,
+ sizeof(HAL_SYSTEM_DOCK_INFORMATION));
+ if (dock == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (dockState == SYSTEM_NOT_DOCKED) {
+
+ //
+ // System is not docked, simply return the dock state.
+ //
+
+ dock->DockState = SystemUndocked;
+ } else {
+
+ //
+ // else system is docked, remember its dock id and serial number.
+ //
+
+ dock->DockState = SystemDocked;
+#if 1
+ MbpBusExtension[0]->DockingStationId = biosDockInfo.LocationId;
+ MbpBusExtension[0]->DockingStationSerialNumber = biosDockInfo.SerialNumber;
+ ExAcquireFastMutex (&MbpMutex);
+ if (biosDockInfo.Capabilities && DOCKING_CAPABILITIES_MASK != DOCKING_CAPABILITIES_COLD_DOCKING) {
+ MbpBusExtension[0]->DockingStationDevice->Flags |= DEVICE_FLAGS_EJECT_SUPPORTED;
+ }
+ ExReleaseFastMutex (&MbpMutex);
+#else
+ if (biosDockInfo.LocationId != UNKNOWN_DOCKING_IDENTIFIER) {
+
+ //
+ // If docking station location Id is present...
+ //
+
+ unicodeString = &MbpBusExtension[0]->DockingStationId;
+ PbDecompressEisaId(biosDockInfo.LocationId, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ dockIdLength = sizeof(WCHAR) * (ansiString.Length + 1);
+ unicodeString->Buffer = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ dockIdLength);
+ if (unicodeString->Buffer == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ unicodeString->MaximumLength = (USHORT)dockIdLength;
+ RtlAnsiStringToUnicodeString(unicodeString, &ansiString, FALSE);
+ }
+// if (biosDockInfo.SerialNumber != 0) {
+
+ //
+ // If docking station serial number is present ...
+ //
+
+ serialLength = sizeof(ULONG) * 2 * sizeof(WCHAR) + sizeof(WCHAR);
+ unicodeString = &MbpBusExtension[0]->DockingStationSerialNo;
+ unicodeString->Buffer = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ serialLength);
+ if (unicodeString->Buffer == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ unicodeString->MaximumLength = (USHORT)serialLength;
+ unicodeString->Length = sizeof(ULONG) * 2 * sizeof(WCHAR);
+ swprintf(unicodeString->Buffer, L"%8x", biosDockInfo.SerialNumber);
+// }
+#endif
+ }
+ dock->DeviceBusType = Internal;
+ dock->DeviceBusNumber = MbpBusNumber[0];
+ dock->SlotNumber = DOCK_VIRTUAL_SLOT_NUMBER;
+ *Length = sizeof(HAL_SYSTEM_DOCK_INFORMATION);
+ *DockInfo = dock;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbpReplyEjectEvent (
+ ULONG SlotNumber,
+ BOOLEAN Eject
+ )
+/*++
+
+Routine Description:
+
+ This function sends message to pnp bios for event processing.
+
+Arguments:
+
+ SlotNumber - specifies the slot whoes data is desired.
+
+ Eject - indicates if EJECT operation should be performed.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status;
+ PB_PARAMETERS biosParameters;
+ USHORT message;
+
+ PAGED_CODE();
+
+ //
+ // Else we need to resort to Pnp Bios runtime API or hardware ...
+ //
+
+ biosParameters.Function = PNP_BIOS_SEND_MESSAGE;
+ if (Eject) {
+ biosParameters.u.SendMessage.Message = OK_TO_CHANGE_CONFIG;
+ } else {
+ biosParameters.u.SendMessage.Message = ABORT_CONFIG_CHANGE;
+ }
+
+ status = PbHardwareService(&biosParameters);
+ return status;
+}
+
+PUCHAR
+MbpFindNextPnpEndTag (
+ IN PUCHAR BusData,
+ IN LONG Limit
+ )
+/*++
+
+Routine Description:
+
+ This function searches the Pnp BIOS device data for the frist END_TAG encountered.
+
+Arguments:
+
+ BusData - supplies a pointer to the pnp bios resource descriptor.
+
+ Limit - maximum length of the search.
+
+Return Value:
+
+ The address of the END_TAG location. Null if not found.
+
+--*/
+{
+ UCHAR tag;
+ USHORT size;
+
+ tag = *BusData;
+ while (tag != TAG_COMPLETE_END && Limit > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(BusData + 1);
+ size += 3; // length of large tag
+ }
+
+ BusData += size;
+ Limit -= size;
+ tag = *BusData;
+ }
+ if (tag == TAG_COMPLETE_END) {
+ return BusData;
+ } else {
+ return NULL;
+ }
+}
+
+BOOLEAN
+MbpConfigAboutToChange (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is invoked by low level component to signal a dock\undock event
+ is about to happen.
+
+ This function is called at DPC level.
+
+Arguments:
+
+ SlotNumber - supplies the docking connector slot number.
+
+Return Value:
+
+ TRUE - allow the change to happen; FALSE - ignore it for now.
+
+--*/
+{
+ PDEVICE_DATA deviceData;
+ HAL_BUS_INFORMATION busInfo;
+ PBUS_HANDLER busHandler;
+
+ //
+ // Get docking station slot data
+ //
+
+ deviceData = MbpFindDeviceData (MbpBusExtension[0], DOCK_VIRTUAL_SLOT_NUMBER);
+ if (deviceData) {
+
+ //
+ // if docking station slot is present
+ //
+
+ ASSERT (deviceData->Flags & DEVICE_FLAGS_DOCKING_STATION);
+
+ //
+ // If it is presently docked, the change is about-to-undock.
+ // We need to notify Eject callback.
+ //
+
+ DebugPrint((DEBUG_MESSAGE, "pnpbios: About to UNDOCK...\n"));
+ busHandler = MbpBusExtension[0]->BusHandler;
+ busInfo.BusType = busHandler->InterfaceType;
+ busInfo.ConfigurationType = busHandler->ConfigurationType;
+ busInfo.BusNumber = busHandler->BusNumber;
+ busInfo.Reserved = 0;
+ ExNotifyCallback (
+ MbpEjectCallbackObject,
+ &busInfo,
+ (PVOID)busHandler->BusNumber
+ );
+ } else {
+
+ DebugPrint((DEBUG_MESSAGE, "pnpbios: About to DOCK...\n"));
+
+ //
+ // Otherwise, it is about-to-dock. Simply let it happen.
+ //
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+VOID
+MbpConfigChanged (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is invoked by low level component to signal a dock-changed,
+ a system-device-changed, or a config-change_failed event. We simply notify
+ bus check callbacks.
+ This function is called at DPC level.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBUS_HANDLER busHandler;
+ ULONG i;
+
+ //
+ // Notify buscheck for ALL the supported buses and queue check bus requests.
+ //
+
+ for (i = 0; i <= 1; i++) {
+ busHandler = MbpBusExtension[i]->BusHandler;
+ if (busHandler) {
+ MbpQueueCheckBus(busHandler);
+ }
+ }
+}
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/busp.h b/private/ntos/nthals/extender/pnpbios/i386/busp.h
new file mode 100644
index 000000000..ca894ea05
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/busp.h
@@ -0,0 +1,499 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busp.h
+
+Abstract:
+
+ Hardware independent header file for pnp bios bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-21-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pbapi.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+//
+// Structures
+//
+
+//
+// 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 virtual slot number for docking station. (We need to return docking
+// station slot number before knowing the real slot number. )
+//
+
+#define DOCK_VIRTUAL_SLOT_NUMBER 0xFFFF
+
+//
+// DEVICE_DATA Flags masks
+//
+
+#define DEVICE_FLAGS_DOCKING_STATION 0x10000000
+#define DEVICE_FLAGS_VALID 0x00000001
+#define DEVICE_FLAGS_WARM_DOCKING 0x00000002
+#define DEVICE_FLAGS_COLD_DOCKING 0x00000004
+#define DEVICE_FLAGS_EJECT_SUPPORTED 0x00000008
+
+typedef struct _DEVICE_DATA_ {
+ SINGLE_LIST_ENTRY Next;
+ ULONG Flags;
+
+ //
+ // DeviceControl in progress flags
+ //
+
+ BOOLEAN SyncBusy;
+
+ //
+ // Pointer to bus specific data
+ //
+
+ PVOID BusData;
+
+ //
+ // Length of the bus data
+ //
+
+ ULONG BusDataLength;
+
+} DEVICE_DATA, *PDEVICE_DATA;
+
+//
+// Extension data for Bus extender
+//
+
+typedef struct _MB_BUS_EXTENSION {
+
+ //
+ // BusHandler points back to the BUS_HANDLER structure for this extension
+ //
+
+ PBUS_HANDLER BusHandler;
+
+ //
+ // Bus Check request list
+ //
+
+ LIST_ENTRY CheckBus;
+
+ //
+ // Device control request list
+ //
+
+ LIST_ENTRY DeviceControl;
+
+ //
+ // Slot Data link list
+ //
+
+ SINGLE_LIST_ENTRY ValidSlots;
+ ULONG NoValidSlots;
+
+ //
+ // Pointer to docking station device data.
+ // This is mainly for convenience.
+ //
+
+ PDEVICE_DATA DockingStationDevice;
+ ULONG DockingStationId;
+ ULONG DockingStationSerialNumber;
+} MB_BUS_EXTENSION, *PMB_BUS_EXTENSION;
+
+typedef struct {
+ BOOLEAN Control;
+} *PBCTL_SET_CONTROL;
+
+//
+// Pnp Bios bus extender device object extension
+//
+
+typedef struct _MB_DEVICE_EXTENSION {
+ PBUS_HANDLER BusHandler;
+} MB_DEVICE_EXTENSION, *PMB_DEVICE_EXTENSION;
+
+//
+// Only support 2 buses: main bus and docking station bus.
+//
+
+#define MAXIMUM_BUS_NUMBER 2
+
+//
+// SlotControl related internal definitions
+//
+
+typedef BOOLEAN (FASTCALL * BEGIN_FUNCTION)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+typedef VOID (* CONTROL_FUNCTION)(PDEVICE_DATA, PHAL_DEVICE_CONTROL_CONTEXT);
+
+typedef struct _DEVICE_CONTROL_HANDLER {
+ ULONG ControlCode;
+ ULONG MinBuffer;
+ BEGIN_FUNCTION BeginDeviceControl;
+ CONTROL_FUNCTION ControlHandler;
+} DEVICE_CONTROL_HANDLER, *PDEVICE_CONTROL_HANDLER;
+
+#define NUMBER_DEVICE_CONTROL_FUNCTIONS 11
+
+//
+// misc. definitions
+//
+
+#define BUS_0_SIGNATURE 0xabababab
+#define MIN_DETECT_SIGNATURE_SIZE (FIELD_OFFSET(CM_RESOURCE_LIST, List) + \
+ FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList))
+
+//
+// Globals
+//
+
+extern FAST_MUTEX MbpMutex;
+extern KSPIN_LOCK MbpSpinlock;
+extern LIST_ENTRY MbpControlWorkerList;
+extern LIST_ENTRY MbpCheckBusList;
+extern ULONG MbpWorkerQueued;
+extern WORK_QUEUE_ITEM MbpWorkItem;
+extern ULONG MbpNextHandle;
+extern DEVICE_CONTROL_HANDLER MbpDeviceControl[];
+extern PDRIVER_OBJECT MbpDriverObject;
+extern HAL_CALLBACKS MbpHalCallbacks;
+extern PCALLBACK_OBJECT MbpEjectCallbackObject;
+extern BOOLEAN MbpNoBusyFlag;
+extern ULONG MbpMaxDeviceData;
+extern PMB_BUS_EXTENSION MbpBusExtension[];
+extern WCHAR rgzBIOSDeviceName[];
+extern ULONG MbpNextBusId;
+extern ULONG MbpBusNumber[];
+
+extern POBJECT_TYPE *IoDeviceHandlerObjectType;
+extern PULONG IoDeviceHandlerObjectSize;
+extern ULONG MbpDeviceHandlerObjectSize;
+
+#define DeviceHandler2DeviceData(a) ((PDEVICE_DATA) (((PUCHAR) a) + MbpDeviceHandlerObjectSize))
+#define DeviceData2DeviceHandler(a) ((PDEVICE_HANDLER_OBJECT) (((PUCHAR) a) - MbpDeviceHandlerObjectSize))
+#define DeviceDataSlot(a) (DeviceData2DeviceHandler(a)->SlotNumber)
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+NTSTATUS
+MbAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN OUT PULONG InstanceNumber
+ );
+
+NTSTATUS
+MbCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ );
+
+ULONG
+MbGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+MbSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+MbGetDeviceData (
+ 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
+MbSetDeviceData (
+ 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
+MbQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+MbDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbpCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+PDEVICE_DATA
+MbpFindDeviceData (
+ IN PMB_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ );
+
+VOID
+MbpStartWorker (
+ VOID
+ );
+
+VOID
+MbpControlWorker (
+ IN PVOID WorkerContext
+ );
+
+VOID
+MbpQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+VOID
+MbpDispatchControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbpCompleteDeviceControl (
+ IN NTSTATUS Status,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context,
+ IN PDEVICE_DATA DeviceData
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlNone (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlSync (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlEject (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+MbBCtlLock (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceId (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceResources (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceResourceRequirements (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlSetDeviceResources (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceUniqueId (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryDeviceCapabilities (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlQueryEject (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlEject (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+MbCtlLock (
+ IN PDEVICE_DATA DeviceData,
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+NTSTATUS
+MbpGetBusData (
+ IN ULONG BusNumber,
+ IN PULONG SlotNumber,
+ IN OUT PVOID *BusData,
+ OUT PULONG Length,
+ OUT PBOOLEAN DockConnector
+ );
+
+NTSTATUS
+MbpGetCompatibleDeviceId (
+ IN PVOID BusData,
+ IN ULONG IdIndex,
+ IN PWCHAR CompatibleId
+ );
+
+NTSTATUS
+MbpGetSlotResources (
+ IN ULONG BusNumber,
+ IN PVOID BusData,
+ OUT PCM_RESOURCE_LIST *CmResources,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+MbpGetSlotResourceRequirements (
+ IN ULONG BusNumber,
+ IN PVOID BusData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+MbpSetSlotResources (
+ OUT PVOID *BusData,
+ IN PCM_RESOURCE_LIST CmResources,
+ IN ULONG Length
+ );
+
+NTSTATUS
+MbpReplyEjectEvent (
+ IN ULONG SlotNumber,
+ IN BOOLEAN Eject
+ );
+
+NTSTATUS
+MbpGetDockInformation (
+ OUT PHAL_SYSTEM_DOCK_INFORMATION *DockInfo,
+ PULONG Length
+ );
+
+PDEVICE_HANDLER_OBJECT
+MbpReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ );
+
+#if 0
+
+//
+// BUGBUG - should be removed...
+//
+
+NTSTATUS
+IoRegisterDetectedDevice(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN PCM_RESOURCE_LIST DetectSignature,
+ OUT PULONG InstanceNumber
+ );
+
+typedef enum _DEVICE_STATUS {
+ DeviceStatusOK,
+ DeviceStatusMalfunction,
+ DeviceStatusDisabled,
+ DeviceStatusRemoved,
+ MaximumDeviceStatus
+} DEVICE_STATUS, *PDEVICE_STATUS;
+
+NTSTATUS
+IoRegisterDevicePath(
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler,
+ IN PUNICODE_STRING NtDeviceObjectPath,
+ IN BOOLEAN PhysicalDevicePath,
+ IN PCM_RESOURCE_LIST Configuration,
+ IN DEVICE_STATUS DeviceStatus
+ );
+
+NTSTATUS
+IoGetDeviceHandler(
+ IN PUNICODE_STRING ServicekeyName,
+ IN ULONG InstanceOrdinal,
+ OUT PDEVICE_HANDLER_OBJECT DeviceHandler
+ );
+
+VOID
+IoReleaseDevicehandler (
+ IN PDEVICE_HANDLER_OBJECT DeviceHandler
+ );
+#endif
diff --git a/private/ntos/nthals/extender/pnpbios/i386/control.c b/private/ntos/nthals/extender/pnpbios/i386/control.c
new file mode 100644
index 000000000..ca9942df7
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/control.c
@@ -0,0 +1,725 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ control.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-23-1995
+ Most of the code is adapted from PCI bus extender.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+VOID
+MbpiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData,
+ PBOOLEAN Sync
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,MbpControlWorker)
+#pragma alloc_text(PAGE,MbpCompleteDeviceControl)
+#endif
+
+VOID
+MbpStartWorker (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used to start a worker thread.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG workerQueued;
+
+ if (!MbpWorkerQueued) {
+ workerQueued = ExInterlockedExchangeUlong (
+ &MbpWorkerQueued,
+ 1,
+ MbpSpinLock
+ );
+
+ if (!workerQueued) {
+ ExQueueWorkItem (&MbpWorkItem, DelayedWorkQueue);
+ }
+ }
+}
+
+VOID
+MbpQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+/*++
+
+Routine Description:
+
+ This function enqueues Bus check request to buscheck list.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the bus handler of the bus to be checked.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ExInterlockedInsertTailList (
+ &MbpCheckBusList,
+ &((PMB_BUS_EXTENSION)BusHandler->BusData)->CheckBus,
+ &MbpSpinlock
+ );
+
+ MbpStartWorker();
+}
+
+VOID
+MbpControlWorker (
+ IN PVOID WorkerContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by a system worker thread.
+
+ The worker thread dequeues any SlotControls which need to be
+ processed and dispatches them.
+
+ It then checks for any check bus request.
+
+Arguments:
+
+ WorkerContext - supplies a pointer to a context for the worker. Here
+ it is always NULL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PLIST_ENTRY entry;
+ PMB_BUS_EXTENSION busExtension;
+ PHAL_DEVICE_CONTROL_CONTEXT context;
+
+ PAGED_CODE ();
+
+ //
+ // process check bus
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &MbpCheckBusList,
+ &MbpSpinlock
+ );
+
+ if (!entry) {
+ break;
+ }
+ busExtension = CONTAINING_RECORD (
+ entry,
+ MB_BUS_EXTENSION,
+ CheckBus
+ );
+
+ MbpCheckBus (busExtension->BusHandler);
+ }
+
+ //
+ // Reset worker item for next time
+ //
+
+ ExInitializeWorkItem (&MbpWorkItem, MbpControlWorker, NULL);
+ ExInterlockedExchangeUlong (&MbpWorkerQueued, 0, MbpSpinLock);
+
+ //
+ // Dispatch pending device controls
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &MbpControlWorkerList,
+ &MbpSpinlock
+ );
+
+ if (!entry) {
+
+ //
+ // All done, exit the loop.
+ //
+
+ break;
+ }
+
+ context = CONTAINING_RECORD (
+ entry,
+ HAL_DEVICE_CONTROL_CONTEXT,
+ ContextWorkQueue,
+ );
+
+ MbpDispatchControl (context);
+ }
+}
+
+VOID
+MbpDispatchControl (
+ 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:
+
+ None.
+
+--*/
+{
+ PDEVICE_CONTROL_HANDLER deviceControlHandler;
+ PMB_BUS_EXTENSION busExtension;
+ PDEVICE_DATA deviceData;
+ KIRQL oldIrql;
+ BOOLEAN enqueueIt;
+ PLIST_ENTRY link;
+
+ deviceControlHandler = (PDEVICE_CONTROL_HANDLER) Context->ContextControlHandler;
+ deviceData = DeviceHandler2DeviceData (Context->DeviceControl.DeviceHandler);
+ busExtension = (PMB_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ ExAcquireFastMutex(&MbpMutex);
+
+ //
+ // Verify the device data is still valid
+ //
+
+ if (!deviceData->Flags & DEVICE_FLAGS_VALID) {
+
+ //
+ // Caller has invalid handle, or handle to a different device
+ //
+
+ DebugPrint ((DEBUG_MESSAGE, "PnpBios: DeviceControl has invalid device handler \n" ));
+ Context->DeviceControl.Status = STATUS_NO_SUCH_DEVICE;
+ ExReleaseFastMutex(&MbpMutex);
+ 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.
+ //
+
+ KeAcquireSpinLock (&MbpSpinlock, &oldIrql);
+ InsertTailList (&busExtension->DeviceControl, link);
+ KeReleaseSpinLock (&MbpSpinlock, oldIrql);
+ ExReleaseFastMutex(&MbpMutex);
+ return ;
+ }
+
+ //
+ // Dispatch the function to it's handler
+ //
+
+ ExReleaseFastMutex(&MbpMutex);
+ deviceControlHandler->ControlHandler (deviceData, Context);
+}
+
+VOID
+MbpiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_DATA DeviceData,
+ PBOOLEAN Sync
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a SlotControl. If another SlotControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+ Status - supplies a NTSTATUS code for the completion.
+
+ Context - supplies a pointer to the original device control context.
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Sync - supplies a BOOLEAN variable to indicate
+
+Return Value:
+
+--*/
+{
+ KIRQL oldIrql;
+ PLIST_ENTRY link;
+ PBOOLEAN busyFlag;
+ BOOLEAN startWorker = FALSE;
+ PMB_BUS_EXTENSION busExtension;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ busyFlag = (PBOOLEAN) Context->ContextBusyFlag;
+ deviceHandler = DeviceData2DeviceHandler(DeviceData);
+ busExtension = (PMB_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Pass it to the hal for completion
+ //
+
+ Context->DeviceControl.Status = Status;
+ HalCompleteDeviceControl (Context);
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ KeAcquireSpinLock (&MbpSpinlock, &oldIrql);
+
+ //
+ // Clear appropiate busy flag
+ //
+
+ *busyFlag = FALSE;
+
+ //
+ // Check to see if there are any pending device controls for
+ // this device. If so, requeue them to the worker thread
+ //
+
+ for (link = busExtension->DeviceControl.Flink;
+ link != &busExtension->DeviceControl;
+ link = link->Flink) {
+
+ Context = CONTAINING_RECORD (link, HAL_DEVICE_CONTROL_CONTEXT, ContextWorkQueue);
+ if (Context->DeviceControl.DeviceHandler == deviceHandler) {
+ RemoveEntryList (link);
+ InsertTailList (&MbpControlWorkerList, link);
+ startWorker = TRUE;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock (&MbpSpinlock, oldIrql);
+
+ if (startWorker) {
+ MbpStartWorker ();
+ }
+}
+
+VOID
+MbpCompleteDeviceControl (
+ 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();
+
+ MbpiCompleteDeviceControl (
+ Status,
+ Context,
+ DeviceData,
+ &DeviceData->SyncBusy
+ );
+}
+
+BOOLEAN
+FASTCALL
+MbBCtlNone (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to indicate there is no synchronization for this
+ device control function.
+
+Arguments:
+
+ Context - supplies a pointer to the device control context.
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // No synchronization needed for this SlotControl
+ //
+
+ Context->ContextBusyFlag = (ULONG) &MbpNoBusyFlag;
+ return FALSE;
+}
+
+BOOLEAN
+FASTCALL
+MbBCtlSync (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize device control request. it checks the
+ state (busy/not busy) of the slot and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // This is a sync command, verify the slot is not busy with a different
+ // command.
+ //
+
+ if (DeviceData->SyncBusy) {
+
+ //
+ // 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
+MbBCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize Eject device control request. it checks the
+ state (busy/not busy) of the device and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the slot control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ BOOLEAN busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ busy = MbBCtlSync (DeviceData, Context);
+
+ if (!busy) {
+
+ //
+ // Set no device in the slot
+ //
+
+ DeviceData->Flags &= ~DEVICE_FLAGS_VALID;
+ DebugPrint ((DEBUG_MESSAGE, "PnpBios: set handle invalid - slot %x for Eject request.\n",
+ DeviceDataSlot(DeviceData)));
+ }
+
+ return busy;
+}
+
+BOOLEAN
+FASTCALL
+MbBCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize LOCK device control request. it checks the
+ state (busy/not busy) of the device and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ BOOLEAN busy;
+
+ //
+ // If Slot is busy, then wait
+ //
+
+ busy = MbBCtlSync (DeviceData, Context);
+#if 0
+ if (!busy) {
+
+ lock = ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer)->Control;
+ if (!lock) {
+
+ //
+ // Set no device in the slot
+ //
+
+ DeviceData->Flags &= ~DEVICE_FLAGS_VALID;
+ }
+ }
+#endif
+ return busy;
+}
+
+VOID
+MbCtlEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to eject the docking station in the docking station
+ slot.
+
+Arguments:
+
+ Context - supplies a pointer to the device control context.
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ if (DeviceData->Flags & DEVICE_FLAGS_DOCKING_STATION) {
+ status = MbpReplyEjectEvent(DeviceDataSlot(DeviceData), TRUE);
+ }
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlLock (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to reject the Pnp Bios About-to-undock event.
+ To accept the about-to-undock event, the EJECT device control function
+ should be used. If lock = TRUE, it will be handled as a reject eject
+ request. If lock = FALSE, it will be handled as an accept reject rquest.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN lock;
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ lock = ((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer)->Control;
+
+ if (DeviceData->Flags & DEVICE_FLAGS_DOCKING_STATION) {
+ status = MbpReplyEjectEvent(DeviceDataSlot(DeviceData), (BOOLEAN)!lock);
+ }
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryEject (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns a referenced pointer to a callback object which
+ the bus extender will notify whenever a given device's eject botton is
+ pressed.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+ PULONG callback;
+
+ callback =(PULONG)((PBCTL_SET_CONTROL) Context->DeviceControl.Buffer);
+ if (DeviceData->Flags == DEVICE_FLAGS_DOCKING_STATION) {
+ if (MbpEjectCallbackObject) {
+ status = STATUS_SUCCESS;
+ *callback = (ULONG)MbpEjectCallbackObject;
+ } else {
+ status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceCapabilities (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the BCTL_DEVICE_CAPABILITIES structure to the caller
+ specified buffer.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBCTL_DEVICE_CAPABILITIES capabilities;
+
+ capabilities = (PBCTL_DEVICE_CAPABILITIES) Context->DeviceControl.Buffer;
+
+ capabilities->PowerSupported = FALSE;
+ capabilities->ResumeSupported = FALSE;
+ capabilities->LockSupported = FALSE;
+ if (DeviceData->Flags && DEVICE_FLAGS_EJECT_SUPPORTED) {
+ capabilities->EjectSupported = TRUE;
+ } else {
+ capabilities->EjectSupported = FALSE;
+ }
+ MbpCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceData);
+}
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/data.c b/private/ntos/nthals/extender/pnpbios/i386/data.c
new file mode 100644
index 000000000..e3c44e2ff
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/data.c
@@ -0,0 +1,159 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbdata.c
+
+Abstract:
+
+ Declares various data which is specific to bus extender architecture and
+ is independent of BIOS.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+//
+// MbpMutex - To synchronize with device handle changes
+//
+
+FAST_MUTEX MbpMutex;
+
+//
+// MbpSpinLock - Lock to protect DeviceControl globals
+//
+
+KSPIN_LOCK MbpSpinlock;
+
+//
+// MbpControlWorkerList - List of device control's which are pending for worker thread
+//
+
+LIST_ENTRY MbpControlWorkerList;
+ULONG MbpWorkerQueued;
+
+//
+// MbpWorkItem - Enqueue for DeviceControl worker thread
+//
+
+WORK_QUEUE_ITEM MbpWorkItem;
+
+//
+// MbpCheckBusList -
+//
+
+LIST_ENTRY MbpCheckBusList;
+
+//
+// Eject callback object
+//
+
+PCALLBACK_OBJECT MbpEjectCallbackObject;
+
+//
+// regBIOSDeviceName
+//
+
+WCHAR rgzBIOSDeviceName[] = L"\\Device\\PnpBios_%d";
+
+//
+// Size of DeviceHandlerObject
+//
+
+ULONG MbpDeviceHandlerObjectSize;
+
+//
+// DeviceControl dispatch table
+//
+
+#define B_EJECT BCTL_EJECT
+#define B_UID BCTL_QUERY_DEVICE_UNIQUE_ID
+#define B_CAPABILITIES BCTL_QUERY_DEVICE_CAPABILITIES
+#define B_ID BCTL_QUERY_DEVICE_ID
+#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
+
+//
+// declare slot control function table.
+// NOTE if the number of entries is changed, the NUMBER_SLOT_CONTROL_FUNCTIONS defined in
+// busp.h must be chnaged accordingly.
+//
+
+DEVICE_CONTROL_HANDLER MbpDeviceControl[] = {
+ B_EJECT, 0, MbBCtlEject, MbCtlEject,
+ B_ID, 32, MbBCtlSync, MbCtlQueryDeviceId,
+ B_UID, 32, MbBCtlSync, MbCtlQueryDeviceUniqueId,
+ B_CAPABILITIES, sizeof(BCTL_DEVICE_CAPABILITIES), MbBCtlSync, MbCtlQueryDeviceCapabilities,
+ B_RES, sizeof(ULONG), MbBCtlSync, MbCtlQueryDeviceResources,
+ B_RES_REQ, sizeof(ULONG), MbBCtlSync, MbCtlQueryDeviceResourceRequirements,
+ B_QUERY_EJECT, sizeof(PVOID), MbBCtlNone, MbCtlQueryEject,
+ B_SET_LOCK, sizeof(BOOLEAN), MbBCtlLock, MbCtlLock,
+ B_SET_RESUME, sizeof(BOOLEAN), NULL, NULL,
+ B_SET_POWER, sizeof(POWER_STATE), NULL, NULL,
+ B_SET_RES, 0, MbBCtlSync, MbCtlSetDeviceResources,
+};
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("PAGE")
+#endif
+
+//
+// Bus Extender driver object
+//
+
+PDRIVER_OBJECT MbpDriverObject;
+
+//
+// Pointers to Hal callback objects
+//
+
+HAL_CALLBACKS MbpHalCallbacks;
+
+//
+// MbpNoBusyFlag - scratch memory location to point at
+//
+
+BOOLEAN MbpNoBusyFlag;
+
+//
+// MbpMaxDeviceData - the maximum device data size
+//
+
+ULONG MbpMaxDeviceData;
+
+//
+// Pointers to bus extension data.
+//
+
+PMB_BUS_EXTENSION MbpBusExtension[2];
+
+//
+// Next Bus number index (i.e. logical bus number)
+//
+
+ULONG MbpNextBusId;
+
+//
+// Array to record bus number of buses
+//
+
+ULONG MbpBusNumber[MAXIMUM_BUS_NUMBER];
diff --git a/private/ntos/nthals/extender/pnpbios/i386/init.c b/private/ntos/nthals/extender/pnpbios/i386/init.c
new file mode 100644
index 000000000..0a921bc07
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/init.c
@@ -0,0 +1,482 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+
+ DriverEntry initialization code for pnp bios bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 21-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+NTSTATUS
+MbInstallBusHandler (
+ IN PBUS_HANDLER MbBus
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(PAGE,MbAddBusDevices)
+#pragma alloc_text(PAGE,MbInstallBusHandler)
+#endif
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks if mother board device info is accessible. If yes it
+ initializes its data structures and invokes h/w dependent initialization
+ routine.
+
+Arguments:
+
+ DriverObject - specifies the driver object for the bus extender.
+
+ RegistryPath - supplies a pointer to a unicode string of the service key name in
+ the CurrentControlSet\Services key for the bus extender.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PVOID p;
+ ULONG length, count, i, bufferSize;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ HAL_BUS_INFORMATION busInfo;
+ PCM_RESOURCE_LIST configuration = NULL;
+ ULONG deviceFlags;
+
+ //
+ // Verify Pnp BIOS is present - perform h/w dependent phase 0 initialization.
+ //
+
+ status = PbInitialize(0, NULL);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Pnp Bios data phase 0 Initialization failed.\n"));
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Get pointers to the Hals callback objects. The one we are really interested
+ // in is Bus Check callback.
+ //
+
+ status = HalQuerySystemInformation (
+ HalCallbackInformation,
+ sizeof (MbpHalCallbacks),
+ &MbpHalCallbacks,
+ &length
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Failed to query Hal callbacks\n"));
+ return status;
+ }
+
+ //
+ // Initialize globals
+ //
+
+ MbpDriverObject = DriverObject;
+ ExInitializeWorkItem (&MbpWorkItem, MbpControlWorker, NULL);
+ KeInitializeSpinLock (&MbpSpinlock);
+ InitializeListHead (&MbpControlWorkerList);
+ InitializeListHead (&MbpCheckBusList);
+ ExInitializeFastMutex (&MbpMutex);
+ MbpDeviceHandlerObjectSize = *IoDeviceHandlerObjectSize;
+
+ for (i = 0; i < MAXIMUM_BUS_NUMBER; i++) {
+ MbpBusNumber[i] = (ULONG) -1;
+ }
+
+ //
+ // Initialize driver object add and detect device entries.
+ //
+
+ DriverObject->DriverExtension->AddDevice = MbAddBusDevices;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = MbCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = MbCreateClose;
+
+ //
+ // Query the devices/buses currently controlled by the bus extender
+ //
+
+ status = IoQueryDeviceEnumInfo (&DriverObject->DriverExtension->ServiceKeyName, &count);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+ for (i = 0; i < count; i++) {
+ status = IoGetDeviceHandler(&DriverObject->DriverExtension->ServiceKeyName,
+ i,
+ &deviceHandler);
+ if (NT_SUCCESS(status)) {
+ bufferSize = sizeof(CM_RESOURCE_LIST);
+tryAgain:
+ configuration = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool,
+ bufferSize
+ );
+ if (!configuration) {
+ IoReleaseDeviceHandler(deviceHandler);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ status = IoQueryDeviceConfiguration(deviceHandler,
+ &busInfo,
+ &deviceFlags,
+ configuration,
+ bufferSize, // buffer size
+ &length // Actual size
+ );
+ IoReleaseDeviceHandler(deviceHandler);
+ if (NT_SUCCESS(status)) {
+
+ //
+ // We know we have two buses at most. If this is the first bus, we will add it
+ // and exit. We don't touch 2nd bus at init time. It should be enumerated
+ // later.
+
+ if (length >= MIN_DETECT_SIGNATURE_SIZE &&
+ configuration->List[0].BusNumber == 0 &&
+ configuration->List[0].InterfaceType == BUS_0_SIGNATURE) {
+ if (deviceFlags == DeviceStatusOK) {
+ MbAddBusDevices(&DriverObject->DriverExtension->ServiceKeyName, &i);
+ ExFreePool(configuration);
+ break;
+ }
+ }
+ } else if (status == STATUS_BUFFER_TOO_SMALL) {
+ ExFreePool(configuration);
+ bufferSize = length;
+ goto tryAgain;
+ }
+ ExFreePool(configuration);
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN OUT PULONG InstanceNumber
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS status;
+ PBUS_HANDLER busHandler;
+ PCM_RESOURCE_LIST detectSignature;
+ UCHAR configuration[sizeof(CM_RESOURCE_LIST)];
+ UNICODE_STRING unicodeString;
+ WCHAR buffer[60];
+ ULONG VirtualBusNumber;
+ PDEVICE_HANDLER_OBJECT deviceHandler = NULL;
+
+ PAGED_CODE();
+ RtlZeroMemory(configuration, sizeof(CM_RESOURCE_LIST));
+
+ //
+ // Check if DriverEntry succeeded ...
+ //
+
+ if (!MbpDriverObject) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ if (*InstanceNumber == PLUGPLAY_NO_INSTANCE) {
+ if (MbpBusNumber[0] == (ULONG) -1) {
+
+ //
+ // If bus handler for Pnp Bios bus 0 has not been installed,
+ // add this bus.
+ //
+ // Register bus handler for bus 0 - motherboard devices
+ //
+
+ status = HalRegisterBusHandler (
+ Internal,
+ -1,
+ (ULONG)-1,
+ Isa, // child of Isa bus # 0
+ 0,
+ sizeof (MB_BUS_EXTENSION),
+ MbInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus 0 handler failed\n"));
+ return status;
+ }
+
+ //
+ // Register the bus with Pnp manager.
+ //
+
+ detectSignature = (PCM_RESOURCE_LIST)configuration;
+ detectSignature->Count = 1;
+ detectSignature->List[0].InterfaceType = BUS_0_SIGNATURE;
+ detectSignature->List[0].BusNumber = 0;
+ status = IoRegisterDetectedDevice (&MbpDriverObject->DriverExtension->ServiceKeyName,
+ detectSignature,
+ InstanceNumber);
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // BUGBUG - unregister bus handler? How?
+ //
+
+ DebugPrint((DEBUG_BREAK,"PnpBios: Failed to register bus 0 to Pnp Mgr\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ } else {
+
+ //
+ // Enumerator should be able to find the docking station bus, if present,
+ // and should call this routine with a valid InstanceNumber. So, if after
+ // bus 0 is registered and enumerator calls this function again with
+ // *InstanceNumber == PLUGPLAY_NO_INSTANCE, it means there is no docking
+ // station bus - bus 1, we can simply return STATUS_NO_MORE_ENTRIES.
+ //
+
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ } else {
+
+ if (MbpBusNumber[0] == (ULONG) -1) {
+
+ //
+ // If bus handler for Pnp Bios bus 0 has not been installed,
+ // add this bus.
+ //
+ // Register bus handler for bus 0 - motherboard devices
+ //
+
+ status = HalRegisterBusHandler (
+ Internal,
+ -1,
+ (ULONG)-1,
+ Isa, // child of Isa bus # 0
+ 0,
+ sizeof (MB_BUS_EXTENSION),
+ MbInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus 0 handler failed\n"));
+ return status;
+ }
+
+ } else if (MbpBusNumber[1] == (ULONG) -1 && MbpBusExtension[0]->DockingStationDevice ) {
+
+ //
+ // If bus 1 has not been registered and docking station is present,
+ // Register bus handler for bus 1 - docking station devices
+ //
+
+ status = HalRegisterBusHandler (
+ Internal,
+ -1,
+ (ULONG)-1,
+ Internal,
+ MbpBusNumber[0],
+ sizeof (MB_BUS_EXTENSION),
+ MbInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register Pnp bus handler for bus 1 failed\n"));
+ return status;
+ }
+ } else {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ }
+
+ //
+ // Call Pnp Io Mgr to register the new device object path
+ //
+
+ swprintf (buffer, rgzBIOSDeviceName, busHandler->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ if (!NT_SUCCESS(status = IoGetDeviceHandler(&MbpDriverObject->DriverExtension->ServiceKeyName,
+ *InstanceNumber, &deviceHandler)) ||
+ !NT_SUCCESS(status = IoRegisterDevicePath(deviceHandler, &unicodeString, TRUE, NULL,
+ DeviceStatusOK))) {
+
+ //
+ // BUGBUG - unregister bus handler? How?
+ //
+
+ if (deviceHandler) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Register NT device path failed\n"));
+ IoReleaseDeviceHandler(deviceHandler);
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Unable to get device handler\n"));
+ }
+ }
+
+ IoReleaseDeviceHandler(deviceHandler);
+
+ //
+ // Perform initial bus check
+ //
+
+ MbpCheckBus(busHandler);
+
+ //
+ // Give non portable part of initialization another chance - phase 1 initialization.
+ //
+
+ PbInitialize(1, busHandler->DeviceObject);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbInstallBusHandler (
+ PBUS_HANDLER MbBus
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked by Hal to initialize BUS_HANDLER structure and its
+ extension.
+
+Arguments:
+
+ MbBus - spplies a pointer to Pnp BIOS bus handler's BUS_HANDLER structure.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ WCHAR buffer[60];
+ UNICODE_STRING unicodeString;
+ PMB_DEVICE_EXTENSION deviceExtension;
+ PMB_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+ PDEVICE_OBJECT deviceObject;
+
+ PAGED_CODE();
+
+ //
+ // Verify there's a parent handler
+ //
+
+ if (!MbBus->ParentHandler) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Create device object for Motherboard/PnpBios bus extender.
+ //
+
+ swprintf (buffer, rgzBIOSDeviceName, MbBus->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ status = IoCreateDevice(
+ MbpDriverObject,
+ sizeof(MB_DEVICE_EXTENSION), // No device extension space
+ &unicodeString,
+ FILE_DEVICE_BUS_EXTENDER,
+ 0,
+ FALSE,
+ &deviceObject
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpBios: Failed to create device object\n"));
+ return status;
+ }
+
+ // ===================================
+ // BUGBUG - need to find a solution
+ //
+
+ deviceObject->Flags &= ~0x80;
+
+ // ==================================
+ deviceExtension = (PMB_DEVICE_EXTENSION) deviceObject->DeviceExtension;
+ deviceExtension->BusHandler = MbBus;
+
+ //
+ // Initialize bus handlers
+ //
+
+ MbBus->DeviceObject = deviceObject;
+ MbBus->GetBusData = (PGETSETBUSDATA) MbGetBusData;
+ MbBus->SetBusData = (PGETSETBUSDATA) MbSetBusData;
+ MbBus->QueryBusSlots = (PQUERY_BUS_SLOTS) MbQueryBusSlots;
+ MbBus->DeviceControl = (PDEVICE_CONTROL) MbDeviceControl;
+ MbBus->ReferenceDeviceHandler = (PREFERENCE_DEVICE_HANDLER) MbpReferenceDeviceHandler;
+ MbBus->GetDeviceData = (PGET_SET_DEVICE_DATA) MbGetDeviceData;
+ MbBus->SetDeviceData = (PGET_SET_DEVICE_DATA) MbSetDeviceData;
+
+ //
+ // Intialize bus extension
+ //
+
+ busExtension = (PMB_BUS_EXTENSION)MbBus->BusData;
+ RtlZeroMemory(busExtension, sizeof(MB_BUS_EXTENSION));
+ busExtension->BusHandler = MbBus;
+
+ MbpBusNumber[MbpNextBusId] = MbBus->BusNumber;
+ MbpBusExtension[MbpNextBusId] = busExtension;
+ MbpNextBusId++;
+
+ InitializeListHead (&busExtension->CheckBus);
+ InitializeListHead (&busExtension->DeviceControl);
+
+ return STATUS_SUCCESS;
+}
+
+
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/misc.c b/private/ntos/nthals/extender/pnpbios/i386/misc.c
new file mode 100644
index 000000000..2fb2210fe
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/misc.c
@@ -0,0 +1,471 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+ This file contains pnp bios bus extender support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 20-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,MbCreateClose)
+#pragma alloc_text(PAGE,PbGetRegistryValue)
+#pragma alloc_text(PAGE,PbDecompressEisaId)
+#endif
+
+
+NTSTATUS
+MbCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles open and close requests such that our device objects
+ can be opened. All it does it to complete the Irp with success.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer to the device object to be opened or closed.
+
+ Irp - supplies a pointer to I/O request packet.
+
+Return Value:
+
+ Always returns STATUS_SUCCESS, since this is a null operation.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( DeviceObject );
+
+ PAGED_CODE();
+
+ //
+ // Null operation. Do not give an I/O boost since no I/O was
+ // actually done. IoStatus.Information should be
+ // FILE_OPENED for an open; it's undefined for a close.
+ //
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = FILE_OPENED;
+
+ IoCompleteRequest( Irp, 0);
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+PbDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decompressed compressed Eisa Id and returns the Id to caller
+ specified character buffer.
+
+Arguments:
+
+ CompressedId - supplies the compressed Eisa Id.
+
+ EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT c1, c2;
+ LONG i;
+
+ PAGED_CODE();
+
+ CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
+ c1 = c2 = (USHORT)CompressedId;
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ for (i = 2; i >= 0; i--) {
+ *(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
+ c1 >>= 5;
+ }
+ EisaId += 3;
+ c1 = c2 = (USHORT)(CompressedId >> 16);
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ sprintf (EisaId, "%04x", c1);
+}
+
+NTSTATUS
+PbGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to retrieve the data for a registry key's value.
+ This is done by querying the value of the key with a zero-length buffer
+ to determine the size of the value, and then allocating a buffer and
+ actually querying the value into the buffer.
+
+ It is the responsibility of the caller to free the buffer.
+
+Arguments:
+
+ KeyHandle - Supplies the key handle whose value is to be queried
+
+ ValueName - Supplies the null-terminated Unicode name of the value.
+
+ Information - Returns a pointer to the allocated data buffer.
+
+Return Value:
+
+ The function value is the final status of the query operation.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PKEY_VALUE_FULL_INFORMATION infoBuffer;
+ ULONG keyValueLength;
+
+ PAGED_CODE();
+
+ RtlInitUnicodeString( &unicodeString, ValueName );
+
+ //
+ // Figure out how big the data value is so that a buffer of the
+ // appropriate size can be allocated.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ (PVOID) NULL,
+ 0,
+ &keyValueLength );
+ if (status != STATUS_BUFFER_OVERFLOW &&
+ status != STATUS_BUFFER_TOO_SMALL) {
+ return status;
+ }
+
+ //
+ // Allocate a buffer large enough to contain the entire key data value.
+ //
+
+ infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
+ if (!infoBuffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Query the data for the key value.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ infoBuffer,
+ keyValueLength,
+ &keyValueLength );
+ if (!NT_SUCCESS( status )) {
+ ExFreePool( infoBuffer );
+ return status;
+ }
+
+ //
+ // Everything worked, so simply return the address of the allocated
+ // buffer to the caller, who is now responsible for freeing it.
+ //
+
+ *Information = infoBuffer;
+ return STATUS_SUCCESS;
+}
+#if DBG
+
+VOID
+PbDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This routine displays debugging message or causes a break.
+
+Arguments:
+
+ Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
+ DEBUG_BREAK - displays message and break.
+
+ DebugMessage - supplies a pointer to the debugging message.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ if (Level == DEBUG_BREAK) {
+ DbgBreakPoint();
+ }
+
+ va_end(ap);
+}
+
+VOID
+MbpDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR c = ' ';
+
+ if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
+ c = 'A';
+ } else if (Desc->Option == IO_RESOURCE_PREFERRED) {
+ c = 'P';
+ }
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
+ Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
+ Desc->u.Port.Alignment,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
+ Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
+ Desc->u.Memory.Alignment,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Interrupt.MinimumVector,
+ Desc->u.Interrupt.MaximumVector
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Dma.MinimumChannel,
+ Desc->u.Dma.MaximumChannel
+ );
+ break;
+ }
+}
+
+VOID
+MbpDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays Io resource requirements list.
+
+Arguments:
+
+ IoList - supplies a pointer to the Io resource requirements list to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIO_RESOURCE_LIST resList;
+ PIO_RESOURCE_DESCRIPTOR resDesc;
+ ULONG listCount, count, i, j;
+
+ DbgPrint("Pnp Bios IO Resource Requirements List for Slot %x -\n", IoList->SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", IoList->AlternativeLists, IoList->BusNumber);
+ listCount = IoList->AlternativeLists;
+ resList = &IoList->List[0];
+ for (i = 0; i < listCount; i++) {
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", resList->Version,
+ resList->Revision, resList->Count);
+ resDesc = &resList->Descriptors[0];
+ count = resList->Count;
+ for (j = 0; j < count; j++) {
+ MbpDumpIoResourceDescriptor(" ", resDesc);
+ resDesc++;
+ }
+ resList = (PIO_RESOURCE_LIST) resDesc;
+ }
+}
+
+VOID
+MbpDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT Level: %x, Vector: %x, Affinity: %x\n",
+ Indent,
+ Desc->u.Interrupt.Level,
+ Desc->u.Interrupt.Vector,
+ Desc->u.Interrupt.Affinity
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA Channel: %x, Port: %x\n",
+ Indent,
+ Desc->u.Dma.Channel,
+ Desc->u.Dma.Port
+ );
+ break;
+ }
+}
+
+VOID
+MbpDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine displays CM resource list.
+
+Arguments:
+
+ CmList - supplies a pointer to CM resource list
+
+ SlotNumber - slot number of the resources
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG count, i;
+
+ fullDesc = &CmList->List[0];
+ DbgPrint("Pnp Bios Cm Resource List for Slot %x -\n", SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", CmList->Count, fullDesc->BusNumber);
+ partialDesc = &fullDesc->PartialResourceList;
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", partialDesc->Version,
+ partialDesc->Revision, partialDesc->Count);
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ MbpDumpCmResourceDescriptor(" ", desc);
+ desc++;
+ }
+}
+#endif
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbapi.h b/private/ntos/nthals/extender/pnpbios/i386/pbapi.h
new file mode 100644
index 000000000..70193117a
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbapi.h
@@ -0,0 +1,235 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ bpapi.h
+
+Abstract:
+
+ This module contins definitions/declarations for pnp bios independent code
+ to call Pnp bios dependent code. This module is considered portable code.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-26-1995
+
+Revision History:
+
+--*/
+
+#include "pbios.h"
+
+//
+// internal structures for resource translation
+//
+
+typedef struct _PB_DEPENDENT_RESOURCES {
+ ULONG Count;
+ UCHAR Flags;
+ UCHAR Priority;
+ struct _PB_DEPENDENT_RESOURCES *Next;
+} PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
+
+#define DEPENDENT_FLAGS_END 1
+
+typedef struct _PB_ATERNATIVE_INFORMATION {
+ PPB_DEPENDENT_RESOURCES Resources;
+ ULONG NoDependentFunctions;
+ ULONG TotalResourceCount;
+} PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
+
+#define PB_CM_FORMAT 0
+#define PB_IO_FORMAT 1
+
+//
+// A big structure for calling Pnp BIOS functions
+//
+
+#define PNP_BIOS_GET_NUMBER_DEVICE_NODES 0
+#define PNP_BIOS_GET_DEVICE_NODE 1
+#define PNP_BIOS_SET_DEVICE_NODE 2
+#define PNP_BIOS_GET_EVENT 3
+#define PNP_BIOS_SEND_MESSAGE 4
+#define PNP_BIOS_GET_DOCK_INFORMATION 5
+// Function 6 is reserved
+#define PNP_BIOS_SELECT_BOOT_DEVICE 7
+#define PNP_BIOS_GET_BOOT_DEVICE 8
+#define PNP_BIOS_SET_OLD_ISA_RESOURCES 9
+#define PNP_BIOS_GET_OLD_ISA_RESOURCES 0xA
+#define PNP_BIOS_GET_ISA_CONFIGURATION 0x40
+
+typedef struct _PB_DOCKING_STATION_INFORMATION {
+ ULONG LocationId;
+ ULONG SerialNumber;
+ USHORT Capabilities;
+} PB_DOCKING_STATION_INFORMATION, *PPB_DOCKING_STATION_INFORMATION;
+
+//
+// definitions of Docking station capabilities.
+//
+
+#define DOCKING_CAPABILITIES_MASK 6
+#define DOCKING_CAPABILITIES_COLD_DOCKING 0
+#define DOCKING_CAPABILITIES_WARM_DOCKING 1
+#define DOCKING_CAPABILITIES_HOT_DOCKING 2
+
+typedef struct _PB_PARAMETERS {
+ USHORT Function;
+ union {
+ struct {
+ USHORT *NumberNodes;
+ USHORT *NodeSize;
+ } GetNumberDeviceNodes;
+
+ struct {
+ USHORT *Node;
+ PPNP_BIOS_DEVICE_NODE NodeBuffer;
+ USHORT Control;
+ } GetDeviceNode;
+
+ struct {
+ USHORT Node;
+ PPNP_BIOS_DEVICE_NODE NodeBuffer;
+ USHORT Control;
+ } SetDeviceNode;
+
+ struct {
+ USHORT *Message;
+ } GetEvent;
+
+ struct {
+ USHORT Message;
+ } SendMessage;
+
+ struct {
+ PB_DOCKING_STATION_INFORMATION *DockingStationInfo;
+ USHORT *DockState;
+ } GetDockInfo;
+ } u;
+} PB_PARAMETERS, *PPB_PARAMETERS;
+
+#define PB_MAXIMUM_STACK_SIZE (sizeof(PB_PARAMETERS) + sizeof(USHORT) * 2)
+
+//
+// PNP BIOS send message api definitions
+//
+
+#define OK_TO_CHANGE_CONFIG 00
+#define ABORT_CONFIG_CHANGE 01
+#define PNP_OS_ACTIVE 0x42
+
+//
+// Control Flags for Get_Device_Node
+//
+
+#define GET_CURRENT_CONFIGURATION 1
+#define GET_NEXT_BOOT_CONFIGURATION 2
+
+//
+// Control Flags for Set_Device_node
+//
+
+#define SET_CONFIGURATION_NOW 1
+#define SET_CONFIGURATION_FOR_NEXT_BOOT 2
+
+//
+// Debug functions
+//
+
+#if DBG
+
+VOID
+MbpDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ );
+
+VOID
+MbpDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ );
+
+#define DEBUG_MESSAGE 1
+#define DEBUG_BREAK 2
+
+VOID PbDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+#define DebugPrint(arg) PbDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
+//
+// External References
+//
+
+extern PPNP_BIOS_INSTALLATION_CHECK PbBiosRegistryData;
+extern PVOID PbBiosKeyInformation;
+
+//
+// prototypes
+//
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ IN UCHAR Format,
+ OUT PUCHAR *ReturnedList,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+PbCmResourcesToBiosResources (
+ IN PCM_RESOURCE_LIST CmResources,
+ IN PUCHAR BiosRequirements,
+ IN PUCHAR *BiosResources,
+ IN PULONG Length
+ );
+
+NTSTATUS
+PbInitialize (
+ IN ULONG Phase,
+ IN PDEVICE_OBJECT DeviceObject
+ );
+
+NTSTATUS
+PbGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ );
+
+NTSTATUS
+PbHardwareService (
+ IN PPB_PARAMETERS Parameters
+ );
+
+VOID
+PbDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ );
+
+BOOLEAN
+PbVerifyBusAdd (
+ VOID
+ );
+
+BOOLEAN
+MbpConfigAboutToChange (
+ VOID
+ );
+
+VOID
+MbpConfigChanged (
+ VOID
+ );
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c b/private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c
new file mode 100644
index 000000000..49a9fbaa3
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbcnvrt.c
@@ -0,0 +1,1562 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xlate.c
+
+Abstract:
+
+ This file contains routines to translate resources between PnP ISA/BIOS
+ format and Windows NT formats.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "pbapi.h"
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ );
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ );
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbCmIrqToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PbCmDmaToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PbCmPortToBiosDescriptor (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PbCmMemoryToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ );
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(PAGE,PbBiosResourcesToNtResources)
+#pragma alloc_text(PAGE,PbIoDescriptorToCmDescriptor)
+#pragma alloc_text(PAGE,PbAddDependentResourcesToList)
+#pragma alloc_text(PAGE,PbBiosIrqToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosDmaToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortFixedToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosMemoryToIoDescriptor)
+#pragma alloc_text(PAGE,PbCmIrqToBiosDescriptor)
+#pragma alloc_text(PAGE,PbCmDmaToBiosDescriptor)
+#pragma alloc_text(PAGE,PbCmPortToBiosDescriptor)
+#pragma alloc_text(PAGE,PbCmMemoryToBiosDescriptor)
+#endif
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ IN UCHAR Format,
+ OUT PUCHAR *ReturnedList,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Bios resource list and generates
+ a NT resource list. The returned Nt resource list could be either IO
+ format or CM format. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ SlotNumber - specifies the slot number of the BIOS resource.
+
+ BiosData - Supplies a pointer to a variable which specifies the bios resource
+ data buffer and which to receive the pointer to next bios resource data.
+
+ Format - PB_CM_FORMAT (0) if convert bios resources to Cm format;
+ PB_IO_FORMAT (1) if convert bios resources to Io format.
+
+ ReturnedList - supplies a variable to receive the desired resource list.
+
+ ReturnedLength - Supplies a variable to receive the length of the resource list.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PUCHAR buffer;
+ USHORT mask16, increment;
+ UCHAR tagName, mask8;
+ NTSTATUS status;
+ PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
+ ULONG commonResCount = 0, dependDescCount = 0, i, j;
+ ULONG alternativeListCount = 0, dependFunctionCount = 0;
+ PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
+ PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
+ BOOLEAN dependent = FALSE;
+ PCM_RESOURCE_LIST cmResourceList;
+ ULONG listSize, noResLists;
+ PUCHAR resourceList = NULL;
+
+ //
+ // First, scan the bios data to determine the memory requirement and
+ // the information to build internal data structures.
+ //
+
+ *ReturnedLength = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ while (tagName != TAG_COMPLETE_END) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ tagName &= SMALL_TAG_MASK;
+ } else {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ }
+
+ //
+ // Based on the type of the BIOS resource, determine the count of
+ // the IO descriptors.
+ //
+
+ switch (tagName) {
+ case TAG_IRQ:
+ mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
+ i = 0;
+ while (mask16) {
+ if (mask16 & 1) {
+ i++;
+ }
+ mask16 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_DMA:
+ mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
+ i = 0;
+ while (mask8) {
+ if (mask8 & 1) {
+ i++;
+ }
+ mask8 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ dependFunctionCount++;
+ break;
+ case TAG_END_DEPEND:
+ dependent = FALSE;
+ alternativeListCount++;
+ break;
+ case TAG_IO_FIXED:
+ case TAG_IO:
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (!dependent) {
+ commonResCount++;
+ } else {
+ dependDescCount++;
+ }
+ break;
+ default:
+
+ //
+ // Unknown tag. Skip it.
+ //
+
+ DebugPrint((DEBUG_BREAK, "BiosToNtResources: unknown tag.\n"));
+ break;
+ }
+
+ //
+ // Move to next bios resource descriptor.
+ //
+
+ buffer += increment;
+ tagName = *buffer;
+ }
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (commonResCount == 0 && dependFunctionCount == 0) {
+ *ReturnedList = NULL;
+ *ReturnedLength = 0;
+ *BiosData = buffer + 2;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Allocate memory for our internal data structures
+ //
+
+ if (dependFunctionCount) {
+ dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
+ PagedPool,
+ dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
+ dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
+ 'bPnP'
+ );
+ if (!dependResources) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ dependResList = dependResources; // remember it so we can free it.
+ }
+
+ if (alternativeListCount) {
+ ASSERT(dependFunctionCount != 0);
+ alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
+ 'bPnP'
+ );
+ if (!alternativeList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit0;
+ }
+ RtlZeroMemory(alternativeList,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
+ );
+ alternativeList[0].Resources = dependResources;
+ }
+ if (commonResCount) {
+ commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
+ PagedPool,
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
+ 'bPnP'
+ );
+ if (!commonResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit1;
+ }
+ }
+
+ //
+ // Now start over again to process the bios data and initialize our internal
+ // resource representation.
+ //
+
+ commonIoDesc = commonResources;
+ dependDescCount = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ dependent = FALSE;
+ while (tagName != TAG_COMPLETE_END) {
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ tagName &= SMALL_TAG_MASK;
+ }
+ switch (tagName) {
+ case TAG_IRQ:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_DMA:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ alternativeList[alternativeListCount].NoDependentFunctions++;
+ if (dependDescCount != 0) {
+
+ //
+ // End of current dependent function
+ //
+
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = 0;
+ dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = dependResources->Next;
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ }
+ if (*buffer & SMALL_TAG_SIZE_MASK) {
+ dependResources->Priority = *(buffer + 1);
+ }
+ dependDescCount = 0;
+ dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
+ buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
+ break;
+ case TAG_END_DEPEND:
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = DEPENDENT_FLAGS_END;
+ dependResources->Next = alternativeList[alternativeListCount].Resources;
+ dependent = FALSE;
+ dependDescCount = 0;
+ alternativeListCount++;
+ alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = alternativeList[alternativeListCount].Resources;
+ buffer++;
+ break;
+ case TAG_IO:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_IO_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ dependDescCount;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ default:
+
+ //
+ // Don't-care tag simpley advance the buffer pointer to next tag.
+ //
+
+ if (*buffer & LARGE_RESOURCE_TAG) {
+ increment = *(buffer+1);
+ increment += 3; // length of large tag
+ } else {
+ increment = (UCHAR)(*buffer) & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ buffer += increment;
+ }
+ tagName = *buffer;
+ }
+
+ if (alternativeListCount != 0) {
+ alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
+ }
+ *BiosData = buffer + 2; // Skip END_TAG
+
+ //
+ // prepare Cm/IoResourceList
+ //
+
+ if (Format == PB_CM_FORMAT) {
+ listSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
+ (commonResCount - 1);
+ } else {
+ ULONG totalDescCount, descCount;
+
+ noResLists = 1;
+ for (i = 0; i < alternativeListCount; i++) {
+ noResLists *= alternativeList[i].NoDependentFunctions;
+ }
+ totalDescCount = 0;
+ for (i = 0; i < alternativeListCount; i++) {
+ descCount = 1;
+ for (j = 0; j < alternativeListCount; j++) {
+ if (j == i) {
+ descCount *= alternativeList[j].TotalResourceCount;
+ } else {
+ descCount *= alternativeList[j].NoDependentFunctions;
+ }
+ }
+ totalDescCount += descCount;
+ }
+ listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
+ sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
+ }
+ resourceList = ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
+ if (!resourceList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit2;
+ }
+ if (Format == PB_CM_FORMAT) {
+ PCM_PARTIAL_RESOURCE_LIST partialResList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+
+ cmResourceList = (PCM_RESOURCE_LIST)resourceList;
+ cmResourceList->Count = 1;
+ cmResourceList->List[0].InterfaceType = Internal;
+ cmResourceList->List[0].BusNumber = BusNumber;
+ partialResList = (PCM_PARTIAL_RESOURCE_LIST)&cmResourceList->List[0].PartialResourceList;
+ partialResList->Version = 0;
+ partialResList->Revision = 0;
+ partialResList->Count = commonResCount;
+ commonIoDesc = commonResources;
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
+ for (i = 0; i < commonResCount; i++) {
+ PbIoDescriptorToCmDescriptor(commonIoDesc, partialDesc);
+ partialDesc++;
+ commonIoDesc++;
+ }
+ } else {
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
+ PIO_RESOURCE_LIST ioResList;
+
+ ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)resourceList;
+ ioResReqList->ListSize = listSize;
+ ioResReqList->InterfaceType = Internal;
+ ioResReqList->BusNumber = BusNumber;
+ ioResReqList->SlotNumber = SlotNumber;
+ ioResReqList->Reserved[0] = 0;
+ ioResReqList->Reserved[1] = 0;
+ ioResReqList->Reserved[2] = 0;
+ ioResReqList->AlternativeLists = noResLists;
+ ioResList = &ioResReqList->List[0];
+
+ //
+ // Build resource lists
+ //
+
+ for (i = 0; i < noResLists; i++) {
+ ULONG size;
+
+ ioResList->Version = 1;
+ ioResList->Revision = 1;
+ buffer = (PUCHAR)&ioResList->Descriptors[0];
+
+ //
+ // Copy common resources to the list
+ //
+
+ if (commonResources) {
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
+ RtlMoveMemory(buffer, commonResources, size);
+ buffer += size;
+ }
+
+ //
+ // Copy dependent functions if any.
+ //
+
+ if (alternativeList) {
+ PbAddDependentResourcesToList(&buffer, 0, alternativeList);
+ }
+
+ //
+ // Update io resource list ptr
+ //
+
+ ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
+ sizeof(IO_RESOURCE_DESCRIPTOR);
+ ioResList = (PIO_RESOURCE_LIST)buffer;
+ }
+ }
+ *ReturnedLength = listSize;
+ status = STATUS_SUCCESS;
+ *ReturnedList = resourceList;
+exit2:
+ if (commonResources) {
+ ExFreePool(commonResources);
+ }
+exit1:
+ if (alternativeList) {
+ ExFreePool(alternativeList);
+ }
+exit0:
+ if (dependResList) {
+ ExFreePool(dependResList);
+ }
+ return status;
+}
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds dependent functions to caller specified list.
+
+Arguments:
+
+ ResourceDescriptor - supplies a pointer to the descriptor buffer.
+
+ ListNo - supplies an index to the AlternativeList.
+
+ AlternativeList - supplies a pointer to the alternativelist array.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPB_DEPENDENT_RESOURCES dependentResources, ptr;
+ ULONG size;
+
+ //
+ // Copy dependent resources to caller supplied list buffer and
+ // update the list buffer pointer.
+ //
+
+ dependentResources = AlternativeList[ListNo].Resources;
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
+ RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
+ *ResourceDescriptor = *ResourceDescriptor + size;
+
+ //
+ // Add dependent resource of next list to caller's buffer
+ //
+
+ if (AlternativeList[ListNo + 1].Resources) {
+ ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
+ } else {
+ ptr = NULL;
+ }
+ if (ptr == NULL) {
+ AlternativeList[ListNo].Resources = dependentResources->Next;
+ if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
+ ptr = dependentResources->Next;
+ }
+ }
+ return ptr;
+}
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Arguments:
+
+ IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
+
+ CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CmDescriptor->Type = IoDescriptor->Type;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ switch (CmDescriptor->Type) {
+ case CmResourceTypePort:
+ CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
+ CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
+ break;
+ case CmResourceTypeInterrupt:
+ CmDescriptor->u.Interrupt.Level =
+ CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
+ CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
+ break;
+ case CmResourceTypeMemory:
+ CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+ CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
+ break;
+ case CmResourceTypeDma:
+ CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
+ CmDescriptor->u.Dma.Port = 0;
+ CmDescriptor->u.Dma.Reserved1 = 0;
+ break;
+ }
+}
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IRQ information to NT usable format.
+ This routine stops when an irq io resource is generated. if there are
+ more irq io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ USHORT mask;
+ ULONG irq;
+ PPNP_IRQ_DESCRIPTOR buffer;
+ UCHAR size, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ size = buffer->Tag & SMALL_TAG_SIZE_MASK;
+ mask = buffer->IrqMask;
+ mask >>= bitPosition;
+ irq = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ irq = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (irq != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeInterrupt;
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (size == 3 && buffer->Information & 0x0C) {
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ IoDescriptor->ShareDisposition = CmResourceShareShared;
+ }
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Interrupt.MinimumVector = irq;
+ IoDescriptor->u.Interrupt.MaximumVector = irq;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current irq tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ *BiosData = (PUCHAR)buffer + size + 1;
+ return status;
+}
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS DMA information to NT usable format.
+ This routine stops when an dma io resource is generated. if there are
+ more dma io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ ULONG dma;
+ PPNP_DMA_DESCRIPTOR buffer;
+ UCHAR mask, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ mask = buffer->ChannelMask;
+ mask >>= bitPosition;
+ dma = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ dma = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (dma != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeDma;
+ IoDescriptor->Flags = 0;
+ IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Dma.MinimumChannel = dma;
+ IoDescriptor->u.Dma.MaximumChannel = dma;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current dma tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return status;
+}
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS FIXED IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_FIXED_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = 1;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS MEMORY information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PUCHAR buffer;
+ UCHAR tag;
+ PHYSICAL_ADDRESS minAddr, maxAddr;
+ ULONG alignment, length;
+ USHORT increment;
+
+ buffer = *BiosData;
+ tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
+ increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
+
+ minAddr.HighPart = 0;
+ maxAddr.HighPart = 0;
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
+ maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
+ maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
+ maxAddr.LowPart = minAddr.LowPart + length - 1;
+ alignment = 1;
+ break;
+ }
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypeMemory;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Memory.MinimumAddress = minAddr;
+ IoDescriptor->u.Memory.MaximumAddress = maxAddr;
+ IoDescriptor->u.Memory.Alignment = alignment;
+ IoDescriptor->u.Memory.Length = length;
+
+ //
+ // Done with current tag, advance pointer to next tag
+ //
+
+ buffer += increment;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbCmResourcesToBiosResources (
+ IN PCM_RESOURCE_LIST CmResources,
+ IN PUCHAR BiosRequirements,
+ IN PUCHAR *BiosResources,
+ IN PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Cm resource list and generates
+ a Pnp BIOS resource list. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ CmResources - Supplies a pointer to a Cm resource list buffer.
+
+ BiosRequirements - supplies a pointer to the PnP BIOS possible resources.
+
+ BiosResources - Supplies a variable to receive the pointer to the
+ converted bios resource buffer.
+
+ Length - supplies a pointer to a variable to receive the length
+ of the Pnp Bios resources.
+
+Return Value:
+
+ a pointer to a Pnp Bios resource list if succeeded. Else,
+ a NULL pointer will be returned.
+
+--*/
+{
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
+ ULONG i, count, length, totalSize = 0;
+ PUCHAR p, biosDesc;
+ NTSTATUS status;
+
+ count = CmResources->List[0].PartialResourceList.Count;
+ if (count == 0 || CmResources->Count != 1) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Allocate max amount of memory
+ //
+
+ p= ExAllocatePoolWithTag(PagedPool,
+ count * sizeof(PNP_MEMORY_DESCRIPTOR),
+ 'bPnP');
+ if (!p) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ cmDesc = CmResources->List[0].PartialResourceList.PartialDescriptors;
+ for (i = 0; i < count; i++) {
+ switch (cmDesc->Type) {
+ case CmResourceTypePort:
+ status = PbCmPortToBiosDescriptor (
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeInterrupt:
+ status = PbCmIrqToBiosDescriptor(
+ BiosRequirements,
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeMemory:
+ status = PbCmMemoryToBiosDescriptor (
+ BiosRequirements,
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeDma:
+ status = PbCmDmaToBiosDescriptor (
+ BiosRequirements,
+ cmDesc,
+ &biosDesc,
+ &length
+ );
+ break;
+ case CmResourceTypeDeviceSpecific:
+ length = cmDesc->u.DeviceSpecificData.DataSize;
+ cmDesc++;
+ cmDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDesc + length);
+ continue;
+ }
+ if (NT_SUCCESS(status)) {
+ cmDesc++;
+ RtlMoveMemory(p, biosDesc, length);
+ ExFreePool(biosDesc);
+ p += length;
+ totalSize += length;
+ } else {
+ ExFreePool(p);
+ break;
+ }
+ }
+ if (NT_SUCCESS(status)) {
+ *p = TAG_COMPLETE_END;
+ p++;
+ *p = 0; // checksum ignored
+ totalSize += 2;
+ }
+ return status;
+}
+
+NTSTATUS
+PbCmIrqToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM IRQ information to Pnp BIOS format.
+ Since there is not enough information in the CM int descriptor to
+ convert it to Pnp BIOS descriptor. We will search the Bios
+ possible resource lists for the corresponding resource information.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the bios possible resource lists.
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+Return Value:
+
+ return a pointer to the desired dma descriptor in the BiosRequirements. Null
+ if not found.
+
+--*/
+{
+ USHORT irqMask;
+ UCHAR tag;
+ PPNP_IRQ_DESCRIPTOR biosDesc;
+ PUCHAR returnDesc;
+ NTSTATUS status;
+ ULONG increment;
+
+ if (!BiosRequirements) {
+ return STATUS_UNSUCCESSFUL;
+ }
+ status = STATUS_UNSUCCESSFUL;
+ if (!(CmDescriptor->u.Interrupt.Level & 0xfffffff0)) {
+ irqMask = 1 << CmDescriptor->u.Interrupt.Level;
+ tag = *BiosRequirements;
+ while (tag != TAG_COMPLETE_END) {
+ if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
+ biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->IrqMask & irqMask) {
+ *Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
+ returnDesc = ExAllocatePoolWithTag(PagedPool,
+ *Length,
+ 'bPnP' );
+ if (!returnDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(returnDesc, BiosRequirements, *Length);
+ *BiosDescriptor = returnDesc;
+ status = STATUS_SUCCESS;
+ }
+
+ break;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ return status;
+}
+
+NTSTATUS
+PbCmDmaToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM DMA information to Pnp BIOS format.
+ Since there is not enough information in the CM descriptor to
+ convert it to Pnp BIOS descriptor. We will search the Bios
+ possible resource lists for the corresponding resource information.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the bios possible resource lists.
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+Return Value:
+
+ return a pointer to the desired dma descriptor in the BiosRequirements. Null
+ if not found.
+
+--*/
+{
+ NTSTATUS status;
+ UCHAR dmaMask, tag;
+ PPNP_DMA_DESCRIPTOR biosDesc;
+ PUCHAR returnDesc;
+ ULONG increment;
+
+ if (!BiosRequirements) {
+ return STATUS_UNSUCCESSFUL;
+ }
+ status = STATUS_UNSUCCESSFUL;
+ if (!(CmDescriptor->u.Dma.Channel & 0xfffffff0)) {
+ dmaMask = 1 << CmDescriptor->u.Dma.Channel;
+ tag = *BiosRequirements;
+ while (tag != TAG_COMPLETE_END) {
+ if ((tag & SMALL_TAG_MASK) == TAG_DMA) {
+ biosDesc = (PPNP_DMA_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->ChannelMask & dmaMask) {
+ *Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
+ returnDesc = ExAllocatePoolWithTag(PagedPool,
+ *Length,
+ 'bPnP' );
+ if (!returnDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(returnDesc, BiosRequirements, *Length);
+ *BiosDescriptor = returnDesc;
+ status = STATUS_SUCCESS;
+ }
+ break;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ return status;
+}
+
+NTSTATUS
+PbCmPortToBiosDescriptor (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM PORT information to Pnp BIOS format.
+ Since there is not enough information in the CM descriptor to
+ convert it to Pnp BIOS full function port descriptor. We will
+ convert it to Pnp Bios fixed PORT descriptor. It is caller's
+ responsibility to release the returned data buffer.
+
+Arguments:
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+ BiosDescriptor - supplies a variable to receive the buffer which contains
+ the desired Bios Port descriptor.
+
+ Length - supplies a variable to receive the size the returned bios port
+ descriptor.
+
+Return Value:
+
+ A NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status;
+ PPNP_PORT_DESCRIPTOR portDesc;
+
+ if (CmDescriptor->u.Port.Start.HighPart != 0 ||
+ CmDescriptor->u.Port.Start.LowPart & 0xffff0000 ||
+ CmDescriptor->u.Port.Length & 0xffffff00) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ portDesc = (PPNP_PORT_DESCRIPTOR) ExAllocatePoolWithTag(
+ PagedPool, sizeof(PNP_PORT_DESCRIPTOR), 'bPnP' );
+ if (!portDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Set the return port descriptor
+ //
+
+ portDesc->Tag = TAG_IO | (sizeof(PNP_PORT_DESCRIPTOR) - 1);
+ portDesc->Information = 1; // 16 bit decoding
+ portDesc->Length = (UCHAR)CmDescriptor->u.Port.Length;
+ portDesc->Alignment = 0; // 1?
+ portDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
+ portDesc->MaximumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
+ *BiosDescriptor = (PUCHAR)portDesc;
+ *Length = sizeof(PNP_PORT_DESCRIPTOR);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbCmMemoryToBiosDescriptor (
+ IN PUCHAR BiosRequirements,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
+ OUT PUCHAR *BiosDescriptor,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates CM Memory information to Pnp BIOS format.
+ Since there is not enough information in the CM descriptor to
+ convert it to Pnp BIOS descriptor. We will search the Bios
+ possible resource lists for the corresponding resource information and
+ build a Pnp BIOS memory descriptor from there. It is caller's responsibility
+ to release the returned buffer.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the bios possible resource lists.
+
+ CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
+
+ BiosDescriptor - supplies a variable to receive the buffer which contains
+ the desired Bios Port descriptor.
+
+ Length - supplies a variable to receive the size the returned bios port
+ descriptor.
+
+Return Value:
+
+ A NTSTATUS code.
+
+--*/
+{
+ UCHAR tag, information;
+ PPNP_FIXED_MEMORY32_DESCRIPTOR memoryDesc;
+ ULONG address, size, length, minAddr, maxAddr, alignment;
+ USHORT increment;
+
+ //
+ // Search the possible resource list to get the information
+ // for the memory range described by CmDescriptor.
+ //
+
+ address = CmDescriptor->u.Memory.Start.LowPart;
+ size = CmDescriptor->u.Memory.Length;
+
+ tag = *BiosRequirements;
+ while (tag != TAG_COMPLETE_END) {
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
+ maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
+ + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
+ maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
+ + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
+ maxAddr = minAddr + length - 1;
+ alignment = 1;
+ break;
+ }
+
+ if (minAddr <= address && maxAddr >= (address + size - 1)) {
+ information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUSHORT)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ if (tag == TAG_COMPLETE_END) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Set up Pnp BIOS memory descriptor
+ //
+
+ memoryDesc = (PPNP_FIXED_MEMORY32_DESCRIPTOR) ExAllocatePoolWithTag(
+ PagedPool, sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR), 'bPnP' );
+ if (!memoryDesc) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ memoryDesc->Tag = TAG_MEMORY32_FIXED;
+ memoryDesc->Length = sizeof (PNP_FIXED_MEMORY32_DESCRIPTOR);
+ memoryDesc->Information = information;
+ memoryDesc->BaseAddress = address;
+ memoryDesc->MemorySize = size;
+ *BiosDescriptor = (PUCHAR)memoryDesc;
+ *Length = sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR);
+ return STATUS_SUCCESS;
+ }
+}
+
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbios.h b/private/ntos/nthals/extender/pnpbios/i386/pbios.h
new file mode 100644
index 000000000..b400da35a
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbios.h
@@ -0,0 +1,241 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbiosp.h
+
+Abstract:
+
+ PnP BIOS/ISA configuration data definitions
+
+Author:
+
+ Shie-Lin Tzong (shielint) April 12, 1995
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+
+//
+// Constants
+//
+
+#define SMALL_RESOURCE_TAG (UCHAR)(0x00)
+#define LARGE_RESOURCE_TAG (UCHAR)(0x80)
+#define SMALL_TAG_MASK 0xf8
+#define SMALL_TAG_SIZE_MASK 7
+
+//
+// Small Resouce Tags with length bits stripped off
+//
+
+#define TAG_VERSION 0x08
+#define TAG_LOGICAL_ID 0x10
+#define TAG_COMPATIBLE_ID 0x18
+#define TAG_IRQ 0x20
+#define TAG_DMA 0x28
+#define TAG_START_DEPEND 0x30
+#define TAG_END_DEPEND 0x38
+#define TAG_IO 0x40
+#define TAG_IO_FIXED 0x48
+#define TAG_VENDOR 0x70
+#define TAG_END 0x78
+
+//
+// Large Resouce Tags
+//
+
+#define TAG_MEMORY 0x81
+#define TAG_ANSI_ID 0x82
+#define TAG_UNICODE_ID 0x83
+#define TAG_LVENDOR 0x84
+#define TAG_MEMORY32 0x85
+#define TAG_MEMORY32_FIXED 0x86
+
+//
+// Complete TAG if applicable.
+//
+
+#define TAG_COMPLETE_COMPATIBLE_ID 0x1C
+#define TAG_COMPLETE_END 0x79
+
+#include "pshpack1.h"
+
+//
+// PNP ISA Port descriptor definition
+//
+
+typedef struct _PNP_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01000111B, small item name = 08, length = 7
+ UCHAR Information; // bit [0] = 1 device decodes full 16 bit addr
+ // = 0 device decodes ISA addr bits[9-0]
+ USHORT MinimumAddress;
+ USHORT MaximumAddress;
+ UCHAR Alignment; // Increment in 1 byte blocks
+ UCHAR Length; // # contiguous Port requested
+} PNP_PORT_DESCRIPTOR, *PPNP_PORT_DESCRIPTOR;
+
+//
+// PNP ISA fixed Port descriptor definition
+//
+
+typedef struct _PNP_FIXED_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01001011B, small item name = 09, length = 3
+ USHORT MinimumAddress;
+ UCHAR Length; // # contiguous Port requested
+} PNP_FIXED_PORT_DESCRIPTOR, *PPNP_FIXED_PORT_DESCRIPTOR;
+
+//
+// PNP ISA IRQ descriptor definition
+//
+
+typedef struct _PNP_IRQ_DESCRIPTOR_ {
+ UCHAR Tag; // 0010001XB small item name = 4 length = 2/3
+ USHORT IrqMask; // bit 0 is irq 0
+ UCHAR Information; // Optional
+} PNP_IRQ_DESCRIPTOR, *PPNP_IRQ_DESCRIPTOR;
+
+//
+// Masks for PNP_IRQ_DESCRIPTOR Information byte
+//
+
+#define PNP_IRQ_LEVEL_MASK 0xC
+#define PNP_IRQ_EDGE_MASK 0x3
+
+//
+// PNP ISA DMA descriptor definition
+//
+
+typedef struct _PNP_DMA_DESCRIPTOR_ {
+ UCHAR Tag; // 00101010B, small item name = 05, length = 2
+ UCHAR ChannelMask; // bit 0 is channel 0
+ UCHAR Flags; // see spec
+} PNP_DMA_DESCRIPTOR, *PPNP_DMA_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY descriptor
+//
+
+typedef struct _PNP_MEMORY_DESCRIPTOR_ {
+ UCHAR Tag; // 10000001B, Large item name = 1
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ USHORT MinimumAddress; // address bit [8-23]
+ USHORT MaximumAddress; // address bit [8-23]
+ USHORT Alignment; // 0x0000 = 64KB
+ USHORT MemorySize; // In 256 byte blocks
+} PNP_MEMORY_DESCRIPTOR, *PPNP_MEMORY_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY32 descriptor
+//
+
+typedef struct _PNP_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000101B, Large item name = 5
+ USHORT Length; // Length of the descriptor = 17
+ UCHAR Information; // See def below
+ ULONG MinimumAddress; // 32 bit addr
+ ULONG MaximumAddress; // 32 bit addr
+ ULONG Alignment; // 32 bit alignment
+ ULONG MemorySize; // 32 bit length
+} PNP_MEMORY32_DESCRIPTOR, *PPNP_MEMORY32_DESCRIPTOR;
+
+//
+// PNP ISA FIXED MEMORY32 descriptor
+//
+
+typedef struct _PNP_FIXED_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000110B, Large item name = 6
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ ULONG BaseAddress; // 32 bit addr
+ ULONG MemorySize; // 32 bit length
+} PNP_FIXED_MEMORY32_DESCRIPTOR, *PPNP_FIXED_MEMORY32_DESCRIPTOR;
+
+#define PNP_MEMORY_ROM_MASK 0x40
+#define PNP_MEMORY_SHADOWABLE_MASK 0x20
+#define PNP_MEMORY_CONTROL_MASK 0x18
+ #define PNP_MEMORY_CONTROL_8BIT 00
+ #define PNP_MEMORY_CONTROL_16BIT 01
+ #define PNP_MEMORY_CONTROL_8AND16BIT 02
+ #define PNP_MEMORY_CONTROL_32BIT 03
+#define PNP_MEMORY_SUPPORT_TYPE_MASK 04
+#define PNP_MEMORY_CACHE_SUPPORT_MASK 02
+#define PNP_MEMORY_WRITE_STATUS_MASK 01
+
+#define UNKNOWN_DOCKING_IDENTIFIER 0xffffffff
+#define UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
+#define FUNCTION_NOT_SUPPORTED 0x82
+#define SYSTEM_NOT_DOCKED 0x87
+
+//
+// Pnp BIOS device node structure
+//
+
+typedef struct _PNP_BIOS_DEVICE_NODE {
+ USHORT Size;
+ UCHAR Node;
+ ULONG ProductId;
+ UCHAR DeviceType[3];
+ USHORT DeviceAttributes;
+ // followed by AllocatedResourceBlock, PossibleResourceBlock
+ // and CompatibleDeviceId
+} PNP_BIOS_DEVICE_NODE, *PPNP_BIOS_DEVICE_NODE;
+
+//
+// DeviceType definition
+//
+
+#define BASE_TYPE_DOCKING_STATION 0xA
+
+//
+// Device attributes definitions
+//
+
+#define DEVICE_DOCKING 0x20
+#define DEVICE_REMOVABLE 0x40
+
+//
+// Pnp BIOS Installation check
+//
+
+typedef struct _PNP_BIOS_INSTALLATION_CHECK {
+ UCHAR Signature[4]; // $PnP (ascii)
+ UCHAR Revision;
+ UCHAR Length;
+ USHORT ControlField;
+ UCHAR Checksum;
+ ULONG EventFlagAddress; // Physical address
+ USHORT RealModeEntryOffset;
+ USHORT RealModeEntrySegment;
+ USHORT ProtectedModeEntryOffset;
+ ULONG ProtectedModeCodeBaseAddress;
+ ULONG OemDeviceId;
+ USHORT RealModeDataBaseAddress;
+ ULONG ProtectedModeDataBaseAddress;
+} PNP_BIOS_INSTALLATION_CHECK, *PPNP_BIOS_INSTALLATION_CHECK;
+
+#include "poppack.h"
+
+//
+// Pnp BIOS ControlField masks
+//
+
+#define PNP_BIOS_CONTROL_MASK 0x3
+#define PNP_BIOS_EVENT_NOT_SUPPORTED 0
+#define PNP_BIOS_EVENT_POLLING 1
+#define PNP_BIOS_EVENT_ASYNC 2
+
+//
+// Pnp Bios event
+//
+
+#define ABOUT_TO_CHANGE_CONFIG 1
+#define DOCK_CHANGED 2
+#define SYSTEM_DEVICE_CHANGED 3
+#define CONFIG_CHANGE_FAILED 4
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm b/private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm
new file mode 100644
index 000000000..4d7857f14
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbiosa.asm
@@ -0,0 +1,89 @@
+ title "Pnp Bios Bus Extender ASM support routines"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; Biosa.asm
+;
+; Abstract:
+;
+; This file contains Pnp Bios Bus Extender ASM support routines.
+;
+; Author:
+;
+; Shie-Lin Tzong (shielint) Apr 16, 1995
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+.xlist
+include callconv.inc ; calling convention macros
+.list
+
+ EXTRNP _RtlMoveMemory, 3
+ EXTRNP _KeI386Call16BitCStyleFunction, 4
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; PbCallPnpBiosWorker (
+; IN ULONG EntryOffset,
+; IN ULONG EntrySelector,
+; IN PUSHORT Parameters,
+; IN ULONG ParameterSize
+; );
+;
+; Routine Description:
+;
+; This routines copies the specified parameters to stack and invokes
+; Pnp Bios Entry point.
+;
+; Arguments:
+;
+; EntryOffset and EntrySelector - supplies the entry point of the bios function.
+;
+; Parameters - Supplies a pointer to argument block.
+;
+; ParameterSize - Size of the argument block
+;
+; Return Value:
+;
+; Registers/context contains the register values returned from pnp bios.
+;
+;--
+
+EntryOffset equ [ebp + 8]
+EntrySelector equ [ebp + 12]
+Parameters equ [ebp + 16]
+ParameterSize equ [ebp + 20]
+
+cPublicProc _PbCallPnpBiosWorker, 4
+
+ push ebp
+ mov ebp, esp
+ sub esp, ParameterSize
+ mov eax, esp
+
+ stdCall _RtlMoveMemory, <eax, Parameters, ParameterSize>
+
+ stdCall _KeI386Call16BitCStyleFunction, <EntryOffset, EntrySelector, Parameters, ParameterSize>
+
+ mov esp, ebp
+ pop ebp
+ stdRET _PbCallPnpBiosWorker
+
+stdENDP _PbCallPnpBiosWorker
+
+_TEXT ends
+ end
diff --git a/private/ntos/nthals/extender/pnpbios/i386/pbiosc.c b/private/ntos/nthals/extender/pnpbios/i386/pbiosc.c
new file mode 100644
index 000000000..0afce8e4b
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/pbiosc.c
@@ -0,0 +1,773 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbiosc.c
+
+Abstract:
+
+ This module contains Pnp BIOS dependent routines. It includes code to initialize
+ 16 bit GDT selectors and to call pnp bios api.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 26-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzBIOSIdentifier[] = L"PNP BIOS";
+
+//
+// PbBiosKeyInformation points to the registry data information
+// which includes key value full information and data.
+//
+
+PVOID PbBiosKeyInformation;
+
+//
+// PbBiosRegistryData points to the pnp bios data
+//
+
+PPNP_BIOS_INSTALLATION_CHECK PbBiosRegistryData;
+
+//
+// PbBiosCodeSelector contains the selector of the PNP
+// BIOS code.
+//
+
+USHORT PbBiosCodeSelector;
+
+//
+// PbBiosDataSelector contains the selector of the PNP
+// BIOS data area (F0000-FFFFF)
+//
+
+USHORT PbBiosDataSelector;
+
+//
+// PbSelectors[] contains general purpose preallocated selectors
+//
+
+USHORT PbSelectors[2];
+
+//
+// PbBiosEventAddress contains the virtual address of the PNP
+// BIOS Event Flag.
+//
+
+PUCHAR PbBiosEventAddress;
+
+//
+// PbBiosEntryPoint contains the Pnp Bios entry offset
+//
+
+ULONG PbBiosEntryPoint;
+
+//
+// PbDockConnectorRegistered
+//
+
+BOOLEAN PbDockConnectorRegistered;
+
+//
+// SpinLock to serialize Pnp Bios call
+//
+
+KSPIN_LOCK PbBiosSpinlock;
+
+//
+// 16 bit protected mode event message address
+//
+
+USHORT PbEventMessageOffset;
+USHORT PbEventMessageSelector;
+USHORT PbBiosEventMessage;
+
+//
+// External References
+//
+
+extern
+USHORT
+PbCallPnpBiosWorker (
+ IN ULONG EntryOffset,
+ IN ULONG EntrySelector,
+ IN PUSHORT Parameters,
+ IN USHORT Size
+ );
+
+extern
+BOOLEAN
+RtlEqualUnicodeString(
+ IN PUNICODE_STRING String1,
+ IN PUNICODE_STRING String2,
+ IN BOOLEAN CaseInSensitive
+ );
+
+extern
+NTSTATUS
+KeI386AllocateGdtSelectors(
+ OUT PUSHORT SelectorArray,
+ IN USHORT NumberOfSelectors
+ );
+
+extern
+NTSTATUS
+KeI386SetGdtSelector (
+ IN ULONG Selector,
+ IN PKGDTENTRY GdtValue
+ );
+
+VOID
+PbTimerRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ );
+
+//
+// Internal prototypes
+//
+
+VOID
+PbAddress32ToAddress16 (
+ IN PVOID Address32,
+ IN PUSHORT Address16,
+ IN USHORT Selector
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PbInitialize)
+#pragma alloc_text(PAGE,PbAddress32ToAddress16)
+#endif
+
+NTSTATUS
+PbInitialize (
+ ULONG Phase,
+ PDEVICE_OBJECT DeviceObject
+ )
+
+/*++
+
+Routine Description:
+
+ At phase 0, this routine checks registry for the data collected by
+ ntdetect.com to make sure PnP Bios is present and initializes the
+ internal data structures for pnp bios bus extender.
+
+ Phase 0 init is called only once at DriverEntry. Phase 1 is called
+ whenever a new bus is registered. If phase 1 is called for bus number
+ 1 (i.e. docking station bus), a timer will be start to poll Pnp Bios
+ event if necessary.
+
+ Note, only Bus 0 (mother board devices) and bus 1 (docking station devices)
+ are supported.
+
+Arguments:
+
+ Phase - supplies a number to indicate the phase of the initialization.
+
+ DeviceObject - a pointer to the bus extender device object. At phase 0,
+ it is NULL.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+{
+ KGDTENTRY gdtEntry;
+ UNICODE_STRING unicodeString, unicodeValueName, biosId;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ WCHAR wbuffer[10];
+ ULONG codeBase, i, length;
+ PWSTR p;
+ PKEY_VALUE_FULL_INFORMATION valueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+ NTSTATUS status;
+ BOOLEAN same;
+ USHORT selectors[4];
+ PHYSICAL_ADDRESS physicalAddr;
+ PVOID virtualAddr;
+ PB_PARAMETERS biosParameters;
+ USHORT pnpControl;
+
+ if (Phase == 1) {
+ if (((PMB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->BusHandler->BusNumber ==
+ MbpBusNumber[0]) {
+ if (PbBiosEventAddress) {
+
+ //
+ // First disable pnp bios default event timeout
+ //
+
+ biosParameters.Function = PNP_BIOS_SEND_MESSAGE;
+ biosParameters.u.SendMessage.Message = PNP_OS_ACTIVE;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpBios: Disable Event timeout failed\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Create timer to poll for PNP BIOS events.
+ //
+
+ IoInitializeTimer (DeviceObject, PbTimerRoutine, NULL);
+ IoStartTimer (DeviceObject);
+ }
+ }
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Look in the registery for the "PNP BIOS bus" data
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (&objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpBIos:Can not open MultifunctionAdapter registry key.\n"));
+ return status;
+ }
+
+ unicodeString.Buffer = wbuffer;
+ unicodeString.MaximumLength = sizeof(wbuffer);
+ RtlInitUnicodeString(&biosId, rgzBIOSIdentifier);
+
+ for (i = 0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Out of Multifunction adapter entries...
+ //
+
+ DebugPrint((DEBUG_MESSAGE, "PnpBIos: Pnp BIOS MultifunctionAdapter registry key not found.\n"));
+ ZwClose (hMFunc);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Check the Indentifier to see if this is a Pnp BIOS entry
+ //
+
+ status = PbGetRegistryValue (hBus, rgzIdentifier, &valueInfo);
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) valueInfo + valueInfo->DataOffset);
+ unicodeValueName.Buffer = p;
+ unicodeValueName.MaximumLength = (USHORT)valueInfo->DataLength;
+ length = valueInfo->DataLength;
+
+ //
+ // Determine the real length of the ID string
+ //
+
+ while (length) {
+ if (p[length / sizeof(WCHAR) - 1] == UNICODE_NULL) {
+ length -= 2;
+ } else {
+ break;
+ }
+ }
+ unicodeValueName.Length = (USHORT)length;
+ same = RtlEqualUnicodeString(&biosId, &unicodeValueName, TRUE);
+ ExFreePool(valueInfo);
+ if (!same) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ status = PbGetRegistryValue(hBus, rgzConfigurationData, &valueInfo);
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ valueInfo + valueInfo->DataOffset);
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ desc->PartialResourceList.PartialDescriptors);
+
+ if (partialDesc->Type == CmResourceTypeDeviceSpecific) {
+
+ //
+ // got it.. Perform sanity check
+ //
+
+ PbBiosRegistryData = (PPNP_BIOS_INSTALLATION_CHECK) (partialDesc+1);
+ if (PbBiosRegistryData->Signature[0] == '$'&&
+ PbBiosRegistryData->Signature[1] == 'P'&&
+ PbBiosRegistryData->Signature[2] == 'n'&&
+ PbBiosRegistryData->Signature[3] == 'P') {
+ PbBiosKeyInformation = (PVOID)valueInfo;
+ ZwClose (hMFunc);
+ break;
+ }
+ }
+ ExFreePool(valueInfo);
+ }
+
+ //
+ // We find the Pnp BIOS data stored by ntdetect.com. Initialize Pnp BIOS
+ // get/set event if supported.
+ //
+
+ pnpControl = PbBiosRegistryData->ControlField & PNP_BIOS_CONTROL_MASK;
+ if ((pnpControl & PNP_BIOS_CONTROL_MASK) != PNP_BIOS_EVENT_NOT_SUPPORTED) {
+ if ((pnpControl & PNP_BIOS_CONTROL_MASK) == PNP_BIOS_EVENT_POLLING) {
+
+ //
+ // Pnp BIOS event notification is supported thru polling. We need
+ // to map event address to non paged pool virtual address.
+ //
+
+ physicalAddr.LowPart = PbBiosRegistryData->EventFlagAddress;
+ physicalAddr.HighPart = 0;
+ virtualAddr = MmMapIoSpace (physicalAddr, 1, FALSE);
+ PbBiosEventAddress = (PUCHAR)virtualAddr;
+ } else if ((pnpControl & PNP_BIOS_CONTROL_MASK) == PNP_BIOS_EVENT_ASYNC) {
+
+ //
+ // Add code here
+ //
+ }
+
+ //
+ // Create eject callback object to notify dock/undock events
+ //
+
+ RtlInitUnicodeString(&unicodeString, L"\\Callback\\PnpBiosEvent");
+
+ InitializeObjectAttributes(
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ status = ExCreateCallback (&MbpEjectCallbackObject, &objectAttributes, TRUE, TRUE);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ }
+
+ //
+ // Allocate 4 or 5 selectors for calling PnP Bios Apis.
+ // If event notification is supported thru polling, we set up an selector for the event
+ // addr (16 bit.). Because the GET EVENT call is made from DPC level and we can not
+ // call kernel routine to set selector at DPC level.
+ //
+
+ if (PbBiosEventAddress) {
+ i = 5;
+ } else {
+ i = 4;
+ }
+ status = KeI386AllocateGdtSelectors (selectors, (USHORT) i);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpBios: Failed to allocate selectors\n"));
+ ExFreePool(valueInfo);
+ return status;
+ }
+
+ PbBiosCodeSelector = selectors[0];
+ PbBiosDataSelector = selectors[1];
+ PbSelectors[0] = selectors[2];
+ PbSelectors[1] = selectors[3];
+
+ PbBiosEntryPoint = (ULONG)PbBiosRegistryData->ProtectedModeEntryOffset;
+
+ //
+ // Initialize selectors to use PNP bios code
+ //
+
+ //
+ // initialize 16 bit code selector
+ //
+
+ gdtEntry.LimitLow = 0xFFFF;
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 31;
+ gdtEntry.HighWord.Bits.Default_Big = 0;
+ physicalAddr.LowPart = PbBiosRegistryData->ProtectedModeCodeBaseAddress;
+ virtualAddr = MmMapIoSpace (physicalAddr, 0x10000, TRUE);
+ codeBase = (ULONG)virtualAddr;
+ gdtEntry.BaseLow = (USHORT) (codeBase & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (codeBase >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (codeBase >> 24) & 0xff;
+ KeI386SetGdtSelector (PbBiosCodeSelector, &gdtEntry);
+
+ //
+ // initialize 16 bit data selector for Pnp BIOS
+ //
+
+ gdtEntry.LimitLow = 0xFFFF;
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 19;
+ gdtEntry.HighWord.Bits.Default_Big = 1;
+ physicalAddr.LowPart = PbBiosRegistryData->ProtectedModeDataBaseAddress;
+ virtualAddr = MmMapIoSpace (physicalAddr, 0x10000, TRUE);
+ codeBase = (ULONG)virtualAddr;
+ gdtEntry.BaseLow = (USHORT) (codeBase & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (codeBase >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (codeBase >> 24) & 0xff;
+ KeI386SetGdtSelector (PbBiosDataSelector, &gdtEntry);
+
+ //
+ // initialize selecot part of message address for calling BIOS
+ //
+
+ if (PbBiosEventAddress) {
+ PbEventMessageSelector = selectors[4];
+ PbEventMessageOffset = 0;
+
+ gdtEntry.LimitLow = 0x3; // 1?
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 19;
+ gdtEntry.HighWord.Bits.Default_Big = 1;
+ codeBase = (ULONG)&PbBiosEventMessage;
+ gdtEntry.BaseLow = (USHORT) (codeBase & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (codeBase >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (codeBase >> 24) & 0xff;
+ KeI386SetGdtSelector (PbEventMessageSelector, &gdtEntry);
+ }
+
+
+ //
+ // Initialize the other two general purpose data selector such that
+ // on subsequent init we only need to init the base addr.
+ //
+
+ KeI386SetGdtSelector (PbSelectors[0], &gdtEntry);
+ KeI386SetGdtSelector (PbSelectors[1], &gdtEntry);
+
+ //
+ // Initialize BIOS call spinlock
+ //
+
+ KeInitializeSpinLock (&PbBiosSpinlock);
+
+ //
+ // Get maximum pnp bios slot data size
+ //
+
+ biosParameters.Function = PNP_BIOS_GET_NUMBER_DEVICE_NODES;
+ biosParameters.u.GetNumberDeviceNodes.NumberNodes = (PUSHORT)&i;
+ biosParameters.u.GetNumberDeviceNodes.NodeSize = (PUSHORT) &MbpMaxDeviceData;
+ status = PbHardwareService(&biosParameters);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbHardwareService (
+ IN PPB_PARAMETERS Parameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up stack parameters and calls an
+ assembly worker routine to actually invoke the PNP BIOS code.
+
+Arguments:
+
+ Parameters - supplies a pointer to the parameter block.
+
+Return Value:
+
+ An NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ USHORT stackParameters[PB_MAXIMUM_STACK_SIZE / 2];
+ ULONG i = 0;
+ USHORT retCode;
+ KIRQL oldIrql;
+
+ //
+ // Convert and copy the caller's parameters to the format that
+ // will be used to invoked pnp bios.
+ //
+
+ stackParameters[i] = Parameters->Function;
+ i++;
+
+ switch (Parameters->Function) {
+ case PNP_BIOS_GET_NUMBER_DEVICE_NODES:
+ PbAddress32ToAddress16(Parameters->u.GetNumberDeviceNodes.NumberNodes,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ PbAddress32ToAddress16(Parameters->u.GetNumberDeviceNodes.NodeSize,
+ &stackParameters[i],
+ PbSelectors[1]);
+ i += 2;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_GET_DEVICE_NODE:
+ PbAddress32ToAddress16(Parameters->u.GetDeviceNode.Node,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ PbAddress32ToAddress16(Parameters->u.GetDeviceNode.NodeBuffer,
+ &stackParameters[i],
+ PbSelectors[1]);
+ i += 2;
+ stackParameters[i++] = Parameters->u.GetDeviceNode.Control;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_SET_DEVICE_NODE:
+ stackParameters[i++] = Parameters->u.SetDeviceNode.Node;
+ PbAddress32ToAddress16(Parameters->u.SetDeviceNode.NodeBuffer,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ stackParameters[i++] = Parameters->u.SetDeviceNode.Control;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_GET_EVENT:
+ stackParameters[i++] = PbEventMessageOffset;
+ stackParameters[i++] = PbEventMessageSelector;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_SEND_MESSAGE:
+ stackParameters[i++] = Parameters->u.SendMessage.Message;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ case PNP_BIOS_GET_DOCK_INFORMATION:
+ PbAddress32ToAddress16(Parameters->u.GetDockInfo.DockingStationInfo,
+ &stackParameters[i],
+ PbSelectors[0]);
+ i += 2;
+ stackParameters[i++] = PbBiosDataSelector;
+ break;
+ default:
+ return STATUS_NOT_IMPLEMENTED;
+
+ }
+
+ //
+ // Copy the parameters to stack and invoke Pnp Bios.
+ //
+
+ KeAcquireSpinLock (&PbBiosSpinlock, &oldIrql);
+
+ retCode = PbCallPnpBiosWorker (
+ PbBiosEntryPoint,
+ PbBiosCodeSelector,
+ stackParameters,
+ (USHORT)(i * sizeof(USHORT)));
+
+ KeReleaseSpinLock (&PbBiosSpinlock, oldIrql);
+
+ //
+ // Special handling for Get Docking station information. We need to
+ // return the docking state (i.e. the returned code.)
+ //
+
+ if (Parameters->Function == PNP_BIOS_GET_DOCK_INFORMATION) {
+ *(Parameters->u.GetDockInfo.DockState) = 0;
+ if (retCode == SYSTEM_NOT_DOCKED) {
+ *(Parameters->u.GetDockInfo.DockState) = retCode;
+ retCode = 0;
+ } else if (retCode == UNABLE_TO_DETERMINE_DOCK_CAPABILITIES) {
+ Parameters->u.GetDockInfo.DockingStationInfo->Capabilities = (USHORT) -1;
+ retCode = 0;
+ }
+ }
+
+ //
+ // Map Bios returned code to nt status code.
+ //
+
+ if (retCode == 0) {
+ return STATUS_SUCCESS;
+ } else {
+ DebugPrint((DEBUG_BREAK, "PnpBios: Bios API call failed.\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+}
+
+VOID
+PbAddress32ToAddress16 (
+ IN PVOID Address32,
+ IN PUSHORT Address16,
+ IN USHORT Selector
+ )
+
+/*++
+
+Routine Description:
+
+ This routine converts the 32 bit address to 16 bit selector:offset address
+ and stored in user specified location.
+
+Arguments:
+
+ Address32 - the 32 bit address to be converted.
+
+ Address16 - supplies the location to receive the 16 bit sel:offset address
+
+ Selector - the 16 bit selector for seg:offset address
+
+Return Value:
+
+ None.
+
+--*/
+{
+ KGDTENTRY gdtEntry;
+ ULONG baseAddr;
+
+ //
+ // Map virtual address to selector:0 address
+ //
+
+ gdtEntry.LimitLow = 0xFFFF;
+ gdtEntry.HighWord.Bytes.Flags1 = 0;
+ gdtEntry.HighWord.Bytes.Flags2 = 0;
+ gdtEntry.HighWord.Bits.Pres = 1;
+ gdtEntry.HighWord.Bits.Dpl = DPL_SYSTEM;
+ gdtEntry.HighWord.Bits.Granularity = GRAN_BYTE;
+ gdtEntry.HighWord.Bits.Type = 19;
+ gdtEntry.HighWord.Bits.Default_Big = 1;
+ baseAddr = (ULONG)Address32;
+ gdtEntry.BaseLow = (USHORT) (baseAddr & 0xffff);
+ gdtEntry.HighWord.Bits.BaseMid = (UCHAR) (baseAddr >> 16) & 0xff;
+ gdtEntry.HighWord.Bits.BaseHi = (UCHAR) (baseAddr >> 24) & 0xff;
+ KeI386SetGdtSelector (Selector, &gdtEntry);
+ *Address16 = 0;
+ *(Address16 + 1) = Selector;
+}
+
+VOID
+PbTimerRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ )
+{
+ PB_PARAMETERS biosParameters;
+ NTSTATUS status;
+ USHORT junk;
+
+ //
+ // Check for Pnp BIOS event
+ //
+
+ if (*PbBiosEventAddress & 1) {
+
+ //
+ // Get Pnp BIOS event.
+ //
+
+ biosParameters.Function = PNP_BIOS_GET_EVENT;
+ biosParameters.u.GetEvent.Message = &PbBiosEventMessage;
+ status = PbHardwareService(&biosParameters);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Process the event ...
+ //
+
+ switch (PbBiosEventMessage) {
+ case ABOUT_TO_CHANGE_CONFIG:
+ DebugPrint((DEBUG_MESSAGE, "PnpBios:Configuration about to change ...\n"));
+ if (MbpConfigAboutToChange()) {
+ biosParameters.Function = PNP_BIOS_SEND_MESSAGE;
+ biosParameters.u.SendMessage.Message = OK_TO_CHANGE_CONFIG;
+ PbHardwareService(&biosParameters);
+ }
+ break;
+
+ case DOCK_CHANGED:
+ case SYSTEM_DEVICE_CHANGED:
+
+ //
+ // For dock, undock and system device changes, we invalidate cached
+ // pnp bios data and notify enumerator to reenumerate the devices.
+ //
+
+ DebugPrint((DEBUG_MESSAGE, "PnpBios:Configuration changed\n"));
+ if (PbBiosKeyInformation) {
+ PbBiosKeyInformation = NULL;
+ PbBiosRegistryData = NULL;
+ ExFreePool(PbBiosKeyInformation);
+ }
+
+ //
+ // Invalidate maximum slot data information after configuration changed.
+ //
+
+ MbpMaxDeviceData = 0;
+
+ MbpConfigChanged();
+ break;
+
+ case CONFIG_CHANGE_FAILED:
+
+ //
+ // do nothing.
+ // BUGBUG - We should define someway to notify the dock/undock
+ // failed. So, user can be notified.
+ //
+
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/private/ntos/nthals/extender/pnpbios/i386/resource.c b/private/ntos/nthals/extender/pnpbios/i386/resource.c
new file mode 100644
index 000000000..daad0c72c
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/i386/resource.c
@@ -0,0 +1,367 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ This module contains the high level device resources support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-25-1995
+ Adapted from Pci bus extender.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+#pragma alloc_text(PAGE,MbCtlQueryDeviceId)
+#pragma alloc_text(PAGE,MbCtlQueryDeviceUniqueId)
+#pragma alloc_text(PAGE,MbCtlQueryDeviceResources)
+#pragma alloc_text(PAGE,MbCtlQueryDeviceResourceRequirements)
+#pragma alloc_text(PAGE,MbCtlSetDeviceResources)
+
+VOID
+MbCtlQueryDeviceUniqueId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the unique id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWCHAR deviceId;
+ ULONG idNumber;
+ PMB_BUS_EXTENSION busExtension;
+
+ PAGED_CODE();
+
+ //
+ // Set up device's unique id.
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+
+ //
+ // If the device is a docking station, we return its docking station
+ // serial number. Else its device id/slot number is returned as the
+ // unique id.
+ //
+
+ if (DeviceData->Flags & DEVICE_FLAGS_DOCKING_STATION) {
+ busExtension = (PMB_BUS_EXTENSION)Context->Handler->BusData;
+ idNumber = busExtension->DockingStationSerialNumber;
+ } else {
+ idNumber = DeviceDataSlot(DeviceData);
+ }
+ swprintf (deviceId, L"%04x", idNumber);
+
+#if DBG
+ {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, (PWCHAR)Context->DeviceControl.Buffer);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x Unique Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceDataSlot(DeviceData),
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ MbpCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+ PWCHAR deviceId;
+ ULONG idIndex;
+
+ PAGED_CODE();
+
+ //
+ // Determine which device ID the caller wants back
+ //
+
+ idIndex = *((PULONG) Context->DeviceControl.Buffer);
+
+ //
+ // Call worker routine to get the desired Id.
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ status = MbpGetCompatibleDeviceId(DeviceData->BusData,
+ idIndex,
+ (PWCHAR) deviceId);
+
+#if DBG
+ if (NT_SUCCESS(status)) {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, deviceId);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x IdIndex %x Compatible Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceDataSlot(DeviceData),
+ idIndex,
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceResources (
+ 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 - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length;
+ PCM_RESOURCE_LIST cmResources;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ status = MbpGetSlotResources(Context->RootHandler->BusNumber,
+ DeviceData->BusData,
+ &cmResources,
+ &length);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ cmResources = (PCM_RESOURCE_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(CM_RESOURCE_LIST), 'bPnP');
+ if (!cmResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ cmResources->Count = 0;
+ cmResources->List[0].InterfaceType = Context->RootHandler->InterfaceType;
+ cmResources->List[0].BusNumber = Context->RootHandler->BusNumber;
+ cmResources->List[0].PartialResourceList.Version = 0;
+ cmResources->List[0].PartialResourceList.Revision = 0;
+ cmResources->List[0].PartialResourceList.Count = 0;
+ length = sizeof(CM_RESOURCE_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, cmResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if DBG
+ if (NT_SUCCESS(status)) {
+ MbpDumpCmResourceList(cmResources, DeviceDataSlot(DeviceData));
+ }
+#endif
+ ExFreePool(cmResources);
+ }
+exitLocal:
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlQueryDeviceResourceRequirements (
+ 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 - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ status = MbpGetSlotResourceRequirements(Context->RootHandler->BusNumber,
+ DeviceData->BusData,
+ &ioResources,
+ &length);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ ioResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST), 'bPnP');
+ if (!ioResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ ioResources->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResources->InterfaceType = Context->RootHandler->InterfaceType;
+ ioResources->BusNumber = Context->RootHandler->BusNumber;
+ ioResources->SlotNumber = DeviceDataSlot(DeviceData);
+ ioResources->Reserved[0] = 0;
+ ioResources->Reserved[1] = 0;
+ ioResources->Reserved[2] = 0;
+ ioResources->AlternativeLists = 0;
+ ioResources->List[0].Version = 1;
+ ioResources->List[0].Revision = 1;
+ ioResources->List[0].Count = 0;
+ length = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, ioResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if DBG
+ if (NT_SUCCESS(status)) {
+ MbpDumpIoResourceList(ioResources);
+ }
+#endif
+ ExFreePool(ioResources);
+ }
+exitLocal:
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
+
+VOID
+MbCtlSetDeviceResources (
+ 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 - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ status = MbpSetSlotResources (
+ &DeviceData->BusData,
+ (PCM_RESOURCE_LIST) Context->DeviceControl.Buffer,
+ *Context->DeviceControl.BufferLength
+ );
+ MbpCompleteDeviceControl (status, Context, DeviceData);
+}
diff --git a/private/ntos/nthals/extender/pnpbios/makefile b/private/ntos/nthals/extender/pnpbios/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/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/pnpbios/pnpbios.rc b/private/ntos/nthals/extender/pnpbios/pnpbios.rc
new file mode 100644
index 000000000..5a305dd63
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/pnpbios.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 "PNP BIOS Extension Driver"
+#define VER_INTERNALNAME_STR "pnpbios.sys"
+#define VER_ORIGINALFILENAME_STR "pnpbios.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pnpbios/sources b/private/ntos/nthals/extender/pnpbios/sources
new file mode 100644
index 000000000..85413d9ed
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpbios/sources
@@ -0,0 +1,49 @@
+!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=extender
+
+TARGETNAME=pnpbios
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=
+
+i386_SOURCES=pnpbios.rc \
+ i386\bus.c \
+ i386\data.c \
+ i386\init.c \
+ i386\control.c \
+ i386\resource.c \
+ i386\busdata.c \
+ i386\pbcnvrt.c \
+ i386\pbiosa.asm \
+ i386\pbiosc.c \
+ i386\misc.c
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=
diff --git a/private/ntos/nthals/extender/pnpisa.sur/bus.c b/private/ntos/nthals/extender/pnpisa.sur/bus.c
new file mode 100644
index 000000000..24955bbf3
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/bus.c
@@ -0,0 +1,962 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ bus.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+
+//
+// Internal references
+//
+
+BOOLEAN
+PipIsDeviceInstanceInstalled(
+ IN HANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PipCheckBus)
+#pragma alloc_text(INIT,PipCheckDevices)
+#pragma alloc_text(INIT,PipDeleteCards)
+#pragma alloc_text(INIT,PipIsDeviceInstanceInstalled)
+#endif
+
+
+VOID
+PipCheckBus (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+
+/*++
+
+Routine Description:
+
+ The function enumerates the bus specified by BusExtension
+
+Arguments:
+
+ BusExtension - supplies a pointer to the BusExtension structure of the bus
+ to be enumerated.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status;
+ ULONG objectSize, noDevices;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ PUCHAR cardData;
+ ULONG dataLength;
+ USHORT csn, i, detectedCsn = 0;
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ UCHAR tmp;
+ PSINGLE_LIST_ENTRY link;
+
+ //
+ // Perform Pnp isolation process. This will assign card select number for each
+ // Pnp Isa card isolated by the system. All the isolated cards will be put into
+ // wait-for-key state.
+ //
+
+ PipIsolateCards(&BusExtension->NumberCSNs);
+
+ //
+ // send initiation key to put cards into sleep state
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // For each card selected build CardInformation and DeviceInformation structures.
+ //
+
+ for (csn = 1; csn <= BusExtension->NumberCSNs; csn++) {
+
+ status = PipReadCardResourceData (
+ csn,
+ &noDevices,
+ &cardData,
+ &dataLength);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ }
+
+ detectedCsn++;
+
+ //
+ // Allocate and initialize card information and its associate device
+ // information structures.
+ //
+
+ cardInfo = (PCARD_INFORMATION)ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof(CARD_INFORMATION),
+ 'iPnP');
+ if (!cardInfo) {
+ ExFreePool(cardData);
+ DebugPrint((DEBUG_MESSAGE, "PnpIsaCheckBus: failed to allocate CARD_INFO structure\n"));
+ continue;
+ }
+
+ //
+ // Initialize card information structure
+ //
+
+ RtlZeroMemory(cardInfo, sizeof(CARD_INFORMATION));
+ cardInfo->CardSelectNumber = csn;
+ cardInfo->NumberLogicalDevices = noDevices;
+ cardInfo->CardData = cardData;
+ cardInfo->CardDataLength = dataLength;
+
+ PushEntryList (&BusExtension->CardList,
+ &cardInfo->CardList
+ );
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsaCheckBus: adding one pnp card %x\n"));
+
+ //
+ // For each logical device supported by the card build its DEVICE_INFORMATION
+ // structures.
+ //
+
+ cardData += sizeof(SERIAL_IDENTIFIER);
+ dataLength -= sizeof(SERIAL_IDENTIFIER);
+ PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+ for (i = 0; i < noDevices; i++) { // logical device number starts from 0
+
+ //
+ // Create and initialize device tracking structure (Device_Information.)
+ //
+
+ deviceInfo = (PDEVICE_INFORMATION) ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof(DEVICE_INFORMATION),
+ 'iPnP');
+ if (!deviceInfo) {
+ DebugPrint((DEBUG_MESSAGE, "PnpIsa:failed to allocate DEVICEINFO structure\n"));
+ continue;
+ }
+
+ deviceInfo->CardInformation = cardInfo;
+ deviceInfo->LogicalDeviceNumber = i;
+ deviceInfo->DeviceData = cardData;
+ deviceInfo->DeviceDataLength = PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+
+ //
+ // Add it to the logical device list of the pnp isa card.
+ //
+
+ PushEntryList (&cardInfo->LogicalDeviceList,
+ &deviceInfo->LogicalDeviceList
+ );
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ BusExtension->NoValidSlots += 1;
+ PushEntryList (&BusExtension->DeviceList,
+ &deviceInfo->DeviceList
+ );
+
+ //
+ // Select the logical device, disable its io range check
+ // (Card is not enabled yet.)
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(i);
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+ BusExtension->NumberCSNs = detectedCsn;
+}
+
+VOID
+PipCheckDevices (
+ PUNICODE_STRING RegistryPath,
+ PPI_BUS_EXTENSION BusExtension
+ )
+
+/*++
+
+Routine Description:
+
+ The function goes through every pnp device and check if it is *installed*,
+ if yes, the device will be enabled. Otherwise, we create a device instance
+ key for the device and leave the device disabled.
+
+Arguments:
+
+ RegistryPath - Supplies a pointer to the registry path passed to the driver
+ entry.
+
+ BusExtension - supplies a pointer to the pnp isa bus extension structure.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status;
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_INFORMATION deviceInfo;
+ PSINGLE_LIST_ENTRY cardLink, deviceLink;
+ PWCHAR cardId, deviceId, uniqueId, compatibleId, ids;
+ WCHAR buffer[128];
+ ULONG disposition, tmpValue, length, cardIdLength;
+ UNICODE_STRING unicodeDeviceId, unicodeUniqueId, unicodeBusId;
+ UNICODE_STRING unicodeDeviceInstance, unicodeString;
+ HANDLE handle, busIdHandle, deviceIdHandle, uniqueIdHandle, logConfHandle;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ PCM_RESOURCE_LIST cmResource;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ UNICODE_STRING madeupInstancePath;
+ HANDLE madeupKeyHandle;
+
+ //
+ // If there is no PnpISA card, we are done.
+ // Oterwise, open HKLM\System\CCS\ENUM\PNPISA.
+ //
+
+ if (BusExtension->NumberCSNs == 0) {
+ return;
+ }
+
+ RtlInitUnicodeString(
+ &unicodeString,
+ L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ FALSE
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open HKLM\\SYSTEM\\CCS\\ENUM"));
+ return;
+ }
+
+ //
+ // Open/Create PNPISA key under HKLM\CCS\System\Enum
+ //
+
+ RtlInitUnicodeString(&unicodeBusId, L"ISAPNP");
+ status = PipOpenRegistryKeyPersist(&busIdHandle,
+ handle,
+ &unicodeBusId,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &disposition
+ );
+ ZwClose(handle);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open ENUM\\PNPISA"));
+ return;
+ }
+
+ //
+ // Since this driver always return failure, Pnp manager will clean up the
+ // madeup key for this driver. If we detect any pnp isa card and create
+ // IsaPnP key. We need to keep the madeup key by deleting its *NewlyCreated*
+ // value entry.
+ //
+
+ status = PipServiceInstanceToDeviceInstance (
+ RegistryPath,
+ 0,
+ &madeupInstancePath,
+ &madeupKeyHandle,
+ KEY_ALL_ACCESS
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open madeup key"));
+ return;
+ }
+ RtlInitUnicodeString(&unicodeString, L"Control");
+ status = PipOpenRegistryKey(&handle,
+ madeupKeyHandle,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ FALSE
+ );
+ if (NT_SUCCESS(status)) {
+ RtlInitUnicodeString(&unicodeString, L"*NewlyCreated*");
+ ZwDeleteValueKey(handle, &unicodeString);
+ ZwClose(handle);
+ }
+
+ //
+ // Go through the card link list to process each of its logical device.
+ //
+
+ for (cardLink = BusExtension->CardList.Next; cardLink; cardLink = cardLink->Next) {
+ cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
+
+ PipGetCardIdentifier((PUCHAR)cardInfo->CardData + NUMBER_CARD_ID_BYTES,
+ &cardId,
+ &cardIdLength);
+
+ //
+ // For each logical device of the card, check if device instance key installed
+ // if yes, we will configure the resource and turn on the device. Otherwise
+ // we create a device instance key and store possible configuration and leave
+ // the device disabled.
+ //
+
+ for (deviceLink = cardInfo->LogicalDeviceList.Next; deviceLink; deviceLink = deviceLink->Next) {
+ deviceInfo = CONTAINING_RECORD (deviceLink,
+ DEVICE_INFORMATION,
+ LogicalDeviceList);
+
+ //
+ // First, get the device id this will be the device key name
+ //
+
+ status = PipQueryDeviceId(deviceInfo, &deviceId, 0);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ } else {
+
+ //
+ // Open/create this registry path under HKLM\CCS\System\Enum\PnPIsa
+ //
+
+ RtlInitUnicodeString(
+ &unicodeDeviceId,
+ deviceId + (unicodeBusId.Length / sizeof(WCHAR)) + 1 );
+ status = PipOpenRegistryKeyPersist(&deviceIdHandle,
+ busIdHandle,
+ &unicodeDeviceId,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &disposition
+ );
+ if (!NT_SUCCESS(status)) {
+ ExFreePool(deviceId);
+ continue;
+ }
+
+ //
+ // Query the unique id for the device
+ //
+
+ status = PipQueryDeviceUniqueId(deviceInfo, &uniqueId);
+ if (!NT_SUCCESS(status)) {
+ ZwClose(deviceIdHandle);
+ ExFreePool(deviceId);
+ continue;
+ }
+
+ //
+ // Open/create this registry device instance path under
+ // HKLM\System\Enum\IsaPnp\deviceId
+ //
+
+ RtlInitUnicodeString(&unicodeUniqueId, uniqueId);
+ status = PipOpenRegistryKeyPersist(&uniqueIdHandle,
+ deviceIdHandle,
+ &unicodeUniqueId,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &disposition
+ );
+ ZwClose(deviceIdHandle);
+ if (!NT_SUCCESS(status)) {
+ ExFreePool(deviceId);
+ ExFreePool(uniqueId);
+ continue;
+ }
+
+ RtlInitUnicodeString(&unicodeString, L"FoundAtEnum");
+ tmpValue = 1;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"LogConf");
+ status = PipOpenRegistryKeyPersist(&logConfHandle,
+ uniqueIdHandle,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ TRUE,
+ &tmpValue
+ );
+ if (!NT_SUCCESS(status)) {
+ logConfHandle = NULL; // just to make sure
+ }
+
+ swprintf(buffer, L"%s\\%s", deviceId, uniqueId);
+ RtlInitUnicodeString(&unicodeDeviceInstance, buffer);
+
+ if (disposition == REG_CREATED_NEW_KEY) {
+
+ //
+ // Create all the default value entry for the newly created key.
+ // DeviceDesc = Card Identifier string
+ // BaseDevicePath = PNPISA a default parent
+ // Configuration = REG_RESOURCE_LIST
+ // ConfigurationVector = REG_RESOUCE_REQUIREMENTS_LIST
+ // HardwareID = MULTI_SZ
+ // CompatibleIDs = MULTI_SZ
+ // ConfigFlags = REG_DWORD CONFIGFLAG_REINSTALL
+ // Status = REG_DWORD DN_HAS_PROBLEM
+ // Problem = REG_DWORD CM_PROB_REINSTALL
+ // Create "Control" volatile subkey.
+ //
+
+ RtlInitUnicodeString(&unicodeString, L"Control");
+ PipOpenRegistryKey(&handle,
+ uniqueIdHandle,
+ &unicodeString,
+ KEY_ALL_ACCESS,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ ZwClose(handle);
+ }
+
+ if (cardId) {
+ RtlInitUnicodeString(&unicodeString, L"DeviceDesc");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_SZ,
+ cardId,
+ cardIdLength
+ );
+ }
+
+ RtlInitUnicodeString(&unicodeString, L"BaseDevicePath");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_SZ,
+ madeupInstancePath.Buffer,
+ madeupInstancePath.Length + sizeof(UNICODE_NULL)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"ConfigFlags");
+ tmpValue = CONFIGFLAG_REINSTALL;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"Problem");
+ tmpValue = CM_PROB_REINSTALL;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"StatusFlags");
+ tmpValue = DN_HAS_PROBLEM;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ if (logConfHandle) {
+ status = PipQueryDeviceResources (
+ deviceInfo,
+ 0, // BusNumber
+ &cmResource,
+ &length
+ );
+
+ if (NT_SUCCESS(status) && cmResource) {
+ RtlInitUnicodeString(&unicodeString, L"BootConfig");
+ ZwSetValueKey(
+ logConfHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_RESOURCE_LIST,
+ cmResource,
+ length
+ );
+ ExFreePool(cmResource);
+ }
+
+ status = PipQueryDeviceResourceRequirements (
+ deviceInfo,
+ 0, // Bus Number
+ 0, // Slot number??
+ &ioResource,
+ &length
+ );
+ if (NT_SUCCESS(status) && ioResource) {
+ RtlInitUnicodeString(&unicodeString, L"BasicConfigVector");
+ ZwSetValueKey(logConfHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_RESOURCE_REQUIREMENTS_LIST,
+ ioResource,
+ length
+ );
+ ExFreePool(ioResource);
+ }
+ }
+
+ status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, 0, &compatibleId);
+ if (NT_SUCCESS(status) && compatibleId) {
+
+ //
+ // create HardwareId value name. Even though it is a MULTI_SZ,
+ // we know there is only one HardwareId for PnpIsa.
+ //
+
+ length = wcslen(compatibleId) * sizeof(WCHAR) + 2 * sizeof(WCHAR);
+ ids = (PWCHAR)ExAllocatePool(PagedPool, length);
+ if (ids) {
+ RtlMoveMemory(ids, compatibleId, length - 2 *sizeof(WCHAR));
+ ids[length / sizeof(WCHAR) - 1] = UNICODE_NULL;
+ ids[length / sizeof(WCHAR) - 2] = UNICODE_NULL;
+ RtlInitUnicodeString(&unicodeString, L"HardwareID");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ ids,
+ length
+ );
+ ExFreePool(ids);
+ }
+ ExFreePool(compatibleId);
+ }
+
+ ids = (PWCHAR)ExAllocatePool(PagedPool, 0x1000);
+ if (ids) {
+ PWCHAR p1;
+ ULONG i;
+
+ p1 = ids;
+ length = 0;
+ for (i = 1; TRUE; i++) {
+ status = PipGetCompatibleDeviceId(
+ deviceInfo->DeviceData,
+ i,
+ &compatibleId);
+ if (NT_SUCCESS(status) && compatibleId) {
+ if ((length + wcslen(compatibleId) * sizeof(WCHAR) + 2 * sizeof(WCHAR))
+ <= 0x1000) {
+ RtlMoveMemory(p1, compatibleId, wcslen(compatibleId) * sizeof(WCHAR));
+ p1 += wcslen(compatibleId);
+ *p1 = UNICODE_NULL;
+ p1++;
+ length += wcslen(compatibleId) * sizeof(WCHAR) + sizeof(WCHAR);
+ ExFreePool(compatibleId);
+ } else {
+ ExFreePool(compatibleId);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ *p1 = UNICODE_NULL;
+ length += sizeof(WCHAR);
+ RtlInitUnicodeString(&unicodeString, L"CompatibleIDs");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ ids,
+ length
+ );
+ ExFreePool(ids);
+ }
+
+ //
+ // Add this device instance key to ENUM\PNPISA AttachedComponents
+ // value entry.
+ //
+
+ PipRemoveStringFromValueKey(
+ madeupKeyHandle,
+ L"AttachedComponents",
+ &unicodeDeviceInstance
+ );
+ PipAppendStringToValueKey(
+ madeupKeyHandle,
+ L"AttachedComponents",
+ &unicodeDeviceInstance,
+ TRUE
+ );
+
+ } else {
+
+ //
+ // The device instance key exists. We need to propagate the ConfigFlag
+ // to problem and StatusFlags
+ //
+
+ ULONG configFlags;
+
+ configFlags = 0;
+ status = PipGetRegistryValue(uniqueIdHandle,
+ L"ConfigFlags",
+ &keyValueInformation);
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_DWORD) &&
+ (keyValueInformation->DataLength >= sizeof(ULONG))) {
+ configFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
+ }
+ ExFreePool(keyValueInformation);
+ }
+ if (configFlags & CONFIGFLAG_REINSTALL) {
+
+ RtlInitUnicodeString(&unicodeString, L"Problem");
+ tmpValue = CM_PROB_REINSTALL;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"StatusFlags");
+ tmpValue = DN_HAS_PROBLEM;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+ } else {
+
+ RtlInitUnicodeString(&unicodeString, L"Problem");
+ tmpValue = 0;
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ RtlInitUnicodeString(&unicodeString, L"StatusFlags");
+ ZwSetValueKey(uniqueIdHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_DWORD,
+ &tmpValue,
+ sizeof(tmpValue)
+ );
+
+ }
+
+
+ //
+ // The device instance key exists. we will enabled the device
+ // if it is installed.
+ //
+
+ if (logConfHandle && PipIsDeviceInstanceInstalled(uniqueIdHandle, &unicodeDeviceInstance)) {
+
+ //
+ // Read the boot config selected by user and activate the device.
+ // First check if ForcedConfig is set. If not, check BootConfig.
+ //
+
+ status = PipGetRegistryValue(logConfHandle,
+ L"ForcedConfig",
+ &keyValueInformation);
+ if (!NT_SUCCESS(status)) {
+ status = PipGetRegistryValue(logConfHandle,
+ L"BootConfig",
+ &keyValueInformation);
+ }
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_RESOURCE_LIST) &&
+ (keyValueInformation->DataLength != 0)) {
+ cmResource = (PCM_RESOURCE_LIST)
+ KEY_VALUE_DATA(keyValueInformation);
+ status = PipSetDeviceResources (deviceInfo, cmResource);
+ if (NT_SUCCESS(status)) {
+ RtlInitUnicodeString(&unicodeString, L"AllocConfig");
+ ZwSetValueKey(logConfHandle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_RESOURCE_LIST,
+ cmResource,
+ keyValueInformation->DataLength
+ );
+ PipSelectLogicalDevice(
+ deviceInfo->CardInformation->CardSelectNumber,
+ deviceInfo->LogicalDeviceNumber,
+ TRUE
+ );
+ }
+ }
+ ExFreePool(keyValueInformation);
+ }
+ }
+ }
+
+ //
+ // Clean up
+ //
+
+ ZwClose(logConfHandle);
+ ZwClose(uniqueIdHandle);
+ ExFreePool(deviceId);
+ ExFreePool(uniqueId);
+ }
+ }
+ if (cardId) {
+ ExFreePool(cardId);
+ }
+ }
+
+ //
+ // Clean up
+ //
+
+ ZwClose(madeupKeyHandle);
+ ZwClose(busIdHandle);
+ ExFreePool(madeupInstancePath.Buffer);
+}
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through card list and deletes all the invalid
+ cards and their associated logical devices.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PSINGLE_LIST_ENTRY *cardLink, *deviceLink ;
+
+ //
+ // Go through the card link list to free all the devices
+ // marked as invalid.
+ //
+
+ cardLink = &BusExtension->CardList.Next;
+ while (*cardLink) {
+ cardInfo = CONTAINING_RECORD (*cardLink, CARD_INFORMATION, CardList);
+
+ //
+ // For each logical device of the card mark it as invalid
+ //
+
+ deviceLink = &cardInfo->LogicalDeviceList.Next;
+ while (*deviceLink) {
+ deviceInfo = CONTAINING_RECORD (*deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
+ BusExtension->NoValidSlots--;
+ *deviceLink = (*deviceLink)->Next; // Get the next addr before releasing pool
+ ExFreePool(deviceInfo);
+ }
+
+ *cardLink = (*cardLink)->Next; // Get the next addr before releasing pool
+ if (cardInfo->CardData) {
+ ExFreePool(cardInfo->CardData);
+ }
+ ExFreePool(cardInfo);
+ }
+
+ //
+ // Reset the CSN number, card and device link lists.
+ //
+
+ BusExtension->NumberCSNs = 0;
+ BusExtension->CardList.Next = NULL;
+ BusExtension->DeviceList.Next = NULL;
+}
+
+BOOLEAN
+PipIsDeviceInstanceInstalled(
+ IN HANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks if the device instance is installed.
+
+Arguments:
+
+ Handle - Supplies a handle to the device instanace key to be checked.
+
+ DeviceInstanceName - supplies a pointer to a UNICODE_STRING which specifies
+ the path of the device instance to be checked.
+
+Returns:
+
+ A BOOLEAN value.
+
+--*/
+
+{
+ NTSTATUS status;
+ ULONG deviceFlags;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ BOOLEAN installed;
+ UNICODE_STRING serviceName, unicodeString;
+ HANDLE handle, handlex;
+
+ //
+ // Check if the "Service=" value entry initialized. If no, its driver
+ // is not installed yet.
+ //
+ status = PipGetRegistryValue(Handle,
+ L"Service",
+ &keyValueInformation);
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_SZ) &&
+ (keyValueInformation->DataLength != 0)) {
+ serviceName.Buffer = (PWSTR)((PCHAR)keyValueInformation +
+ keyValueInformation->DataOffset);
+ serviceName.MaximumLength = serviceName.Length = (USHORT)keyValueInformation->DataLength;
+ if (serviceName.Buffer[keyValueInformation->DataLength / sizeof(WCHAR)] == UNICODE_NULL) {
+ serviceName.Length -= sizeof(WCHAR);
+ }
+
+ //
+ // try open the service key to make sure it is a valid key
+ //
+
+ RtlInitUnicodeString(
+ &unicodeString,
+ L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES");
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ &unicodeString,
+ KEY_READ,
+ FALSE
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsaCheckDeviceInstalled: Can not open CCS\\SERVICES key"));
+ ExFreePool(keyValueInformation);
+ return FALSE;
+ }
+
+ status = PipOpenRegistryKey(&handlex,
+ handle,
+ &serviceName,
+ KEY_READ,
+ FALSE
+ );
+ ZwClose (handle);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsaCheckDeviceInstalled: Can not open CCS\\SERVICES key"));
+ ExFreePool(keyValueInformation);
+ return FALSE;
+ }
+ ZwClose(handlex);
+ }
+ ExFreePool(keyValueInformation);
+ } else {
+ return FALSE;
+ }
+
+ //
+ // Check if the device instance has been disabled.
+ // First check global flag: CONFIGFLAG and then CSCONFIGFLAG.
+ //
+
+ deviceFlags = 0;
+ status = PipGetRegistryValue(Handle,
+ L"ConfigFlags",
+ &keyValueInformation);
+ if (NT_SUCCESS(status)) {
+ if ((keyValueInformation->Type == REG_DWORD) &&
+ (keyValueInformation->DataLength >= sizeof(ULONG))) {
+ deviceFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
+ }
+ ExFreePool(keyValueInformation);
+ }
+
+ if (!(deviceFlags & CONFIGFLAG_DISABLED)) {
+ deviceFlags = 0;
+ status = PipGetDeviceInstanceCsConfigFlags(
+ DeviceInstanceName,
+ &deviceFlags
+ );
+ if (NT_SUCCESS(status)) {
+ if ((deviceFlags & CSCONFIGFLAG_DISABLED) ||
+ (deviceFlags & CSCONFIGFLAG_DO_NOT_CREATE)) {
+ deviceFlags = CONFIGFLAG_DISABLED;
+ } else {
+ deviceFlags = 0;
+ }
+ }
+ }
+
+ installed = TRUE;
+ if (deviceFlags & CONFIGFLAG_DISABLED) {
+ installed = FALSE;
+ }
+
+ return installed;
+}
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/busp.h b/private/ntos/nthals/extender/pnpisa.sur/busp.h
new file mode 100644
index 000000000..d8fd12f07
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/busp.h
@@ -0,0 +1,473 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busp.h
+
+Abstract:
+
+ Hardware independent header file for Pnp Isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+#ifndef _KERNEL_PNPI_
+#define _KERNEL_PNPI_
+#endif
+
+#include <ntddk.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <regstr.h>
+
+#define TITLE_INDEX_VALUE 0
+#define CM_PROB_REINSTALL (0x00000012) // HACK
+#define DN_HAS_PROBLEM (0x00000400)
+#define KEY_VALUE_DATA(k) ((PCHAR)(k) + (k)->DataOffset)
+
+//
+// Structures
+//
+
+//
+// CARD_INFORMATION Flags masks
+//
+
+typedef struct _CARD_INFORMATION_ {
+
+ //
+ // Next points to next CARD_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+
+ //
+ // Card select number for this Pnp Isa card.
+ //
+
+ USHORT CardSelectNumber;
+
+ //
+ // Number logical devices in the card.
+ //
+
+ ULONG NumberLogicalDevices;
+
+ //
+ // Logical device link list
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // Pointer to card data which includes:
+ // 9 byte serial identifier for the pnp isa card
+ // PlugPlay Version number type for the pnp isa card
+ // Identifier string resource type for the pnp isa card
+ // Logical device Id resource type (repeat for each logical device)
+ //
+
+ PVOID CardData;
+ ULONG CardDataLength;
+
+} CARD_INFORMATION, *PCARD_INFORMATION;
+
+//
+// DEVICE_INFORMATION Flags masks
+//
+
+typedef struct _DEVICE_INFORMATION_ {
+
+ //
+ // Link list for ALL the Pnp Isa logical devices.
+ // NextDevice points to next DEVICE_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+
+ //
+ // Pointer to the CARD_INFORMATION for this device
+ //
+
+ PCARD_INFORMATION CardInformation;
+
+ //
+ // Link list for all the logical devices in a Pnp Isa card.
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // LogicalDeviceNumber selects the corresponding logical device in the
+ // pnp isa card specified by CSN.
+ //
+
+ USHORT LogicalDeviceNumber;
+
+ //
+ // Pointer to device specific data
+ //
+
+ PUCHAR DeviceData;
+
+ //
+ // Length of the device data
+ //
+
+ ULONG DeviceDataLength;
+
+} DEVICE_INFORMATION, *PDEVICE_INFORMATION;
+
+//
+// Extension data for Bus extender
+//
+
+typedef struct _PI_BUS_EXTENSION {
+
+ //
+ // Number of cards selected
+ //
+
+ ULONG NumberCSNs;
+
+ //
+ // ReadDataPort addr
+ //
+
+ PUCHAR ReadDataPort;
+ BOOLEAN DataPortMapped;
+
+ //
+ // Address Port
+ //
+
+ PUCHAR AddressPort;
+ BOOLEAN AddrPortMapped;
+
+ //
+ // Command port
+ //
+
+ PUCHAR CommandPort;
+ BOOLEAN CmdPortMapped;
+
+ //
+ // Next Slot Number to assign
+ //
+
+ ULONG NextSlotNumber;
+
+ //
+ // DeviceList is the DEVICE_INFORMATION link list.
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+
+ //
+ // NoValidSlots is the number of valid slots
+ //
+
+ ULONG NoValidSlots;
+
+ //
+ // CardList is the list of CARD_INFORMATION
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+
+} PI_BUS_EXTENSION, *PPI_BUS_EXTENSION;
+
+//
+// The read data port range is from 0x200 - 0x3ff.
+// We will try the following optimal ranges first
+// if they all fail, we then pick any port from 0x200 - 0x3ff
+//
+// BEST:
+// One 4-byte range in 274-2FF
+// One 4-byte range in 374-3FF
+// One 4-byte range in 338-37F
+// One 4-byte range in 238-27F
+//
+// NORMAL:
+// One 4-byte range in 200-3FF
+//
+
+#define READ_DATA_PORT_RANGE_CHOICES 5
+typedef struct _READ_DATA_PORT_RANGE {
+ ULONG MinimumAddress;
+ ULONG MaximumAddress;
+ ULONG Alignment;
+} READ_DATA_PORT_RANGE, *PREAD_DATA_PORT_RANGE;
+
+//
+// Global Data references
+//
+
+extern PI_BUS_EXTENSION PipBusExtension;
+extern WCHAR rgzPNPISADeviceName[];
+extern PUCHAR PipReadDataPort;
+extern PUCHAR PipCommandPort;
+extern PUCHAR PipAddressPort;
+extern READ_DATA_PORT_RANGE PipReadDataPortRanges[];
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+NTSTATUS
+PipGetCardIdentifier (
+ PUCHAR CardData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ );
+
+NTSTATUS
+PipGetFunctionIdentifier (
+ PUCHAR DeviceData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ );
+
+NTSTATUS
+PipQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId
+ );
+
+NTSTATUS
+PipQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId,
+ ULONG IdIndex
+ );
+
+NTSTATUS
+PipQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ PCM_RESOURCE_LIST *CmResources,
+ PULONG Length
+ );
+
+NTSTATUS
+PipQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ ULONG Slot,
+ PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ ULONG *Size
+ );
+
+NTSTATUS
+PipSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ );
+
+NTSTATUS
+PipOpenRegistryKey(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create
+ );
+
+NTSTATUS
+PipOpenRegistryKeyPersist(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create,
+ OUT PULONG Disposition OPTIONAL
+ );
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ );
+
+NTSTATUS
+PipOpenCurrentHwProfileDeviceInstanceKey(
+ OUT PHANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName,
+ IN ACCESS_MASK DesiredAccess
+ );
+
+NTSTATUS
+PipGetDeviceInstanceCsConfigFlags(
+ IN PUNICODE_STRING DeviceInstance,
+ OUT PULONG CsConfigFlags
+ );
+
+NTSTATUS
+PipRemoveStringFromValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String
+ );
+
+NTSTATUS
+PipAppendStringToValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String,
+ IN BOOLEAN Create
+ );
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ );
+
+VOID
+PipCheckBus (
+ IN PPI_BUS_EXTENSION BusExtension
+ );
+
+VOID
+PipCheckDevices (
+ IN PUNICODE_STRING RegistryPath,
+ IN PPI_BUS_EXTENSION BusExtension
+ );
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PVOID *ResourceData,
+ OUT PULONG ResourceDataLength
+ );
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber,
+ IN BOOLEAN ActivateDevice
+ );
+
+VOID
+PipLFSRInitiation (
+ VOID
+ );
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs
+ );
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ );
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION busExtension
+ );
+
+NTSTATUS
+PipServiceInstanceToDeviceInstance (
+ IN PUNICODE_STRING RegistryPath,
+ IN ULONG ServiceInstanceOrdinal,
+ OUT PUNICODE_STRING DeviceInstanceRegistryPath OPTIONAL,
+ OUT PHANDLE DeviceInstanceHandle OPTIONAL,
+ IN ACCESS_MASK DesiredAccess
+ );
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR *Buffer
+ );
+
+NTSTATUS
+ZwDeleteValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName
+ );
+
+#if DBG
+
+#define DEBUG_MESSAGE 1
+#define DEBUG_BREAK 2
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ );
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList
+ );
+
+#define DebugPrint(arg) PipDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/convert.c b/private/ntos/nthals/extender/pnpisa.sur/convert.c
new file mode 100644
index 000000000..1e144bb5e
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/convert.c
@@ -0,0 +1,1092 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xlate.c
+
+Abstract:
+
+ This file contains routines to translate resources between PnP ISA/BIOS
+ format and Windows NT formats.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "pbios.h"
+
+//
+// internal structures for resource translation
+//
+
+typedef struct _PB_DEPENDENT_RESOURCES {
+ ULONG Count;
+ UCHAR Flags;
+ UCHAR Priority;
+ struct _PB_DEPENDENT_RESOURCES *Next;
+} PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
+
+#define DEPENDENT_FLAGS_END 1
+
+typedef struct _PB_ATERNATIVE_INFORMATION {
+ PPB_DEPENDENT_RESOURCES Resources;
+ ULONG NoDependentFunctions;
+ ULONG TotalResourceCount;
+} PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
+
+//
+// Internal function references
+//
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ );
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ );
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(INIT,PbBiosResourcesToNtResources)
+#pragma alloc_text(INIT,PbIoDescriptorToCmDescriptor)
+#pragma alloc_text(INIT,PbAddDependentResourcesToList)
+#pragma alloc_text(INIT,PbBiosIrqToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosDmaToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosPortFixedToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosPortToIoDescriptor)
+#pragma alloc_text(INIT,PbBiosMemoryToIoDescriptor)
+#endif
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Bios resource list and generates
+ a NT resource list. The returned Nt resource list could be either IO
+ format or CM format. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ SlotNumber - specifies the slot number of the BIOS resource.
+
+ BiosData - Supplies a pointer to a variable which specifies the bios resource
+ data buffer and which to receive the pointer to next bios resource data.
+
+ ReturnedList - supplies a variable to receive the desired resource list.
+
+ ReturnedLength - Supplies a variable to receive the length of the resource list.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PUCHAR buffer;
+ USHORT mask16, increment;
+ UCHAR tagName, mask8;
+ NTSTATUS status;
+ PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
+ ULONG commonResCount = 0, dependDescCount = 0, i, j;
+ ULONG alternativeListCount = 0, dependFunctionCount = 0;
+ PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
+ PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
+ BOOLEAN dependent = FALSE;
+ ULONG listSize, noResLists;
+ ULONG totalDescCount, descCount;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
+ PIO_RESOURCE_LIST ioResList;
+
+ //
+ // First, scan the bios data to determine the memory requirement and
+ // the information to build internal data structures.
+ //
+
+ *ReturnedLength = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ while (tagName != TAG_COMPLETE_END) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ tagName &= SMALL_TAG_MASK;
+ } else {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ }
+
+ //
+ // Based on the type of the BIOS resource, determine the count of
+ // the IO descriptors.
+ //
+
+ switch (tagName) {
+ case TAG_IRQ:
+ mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
+ i = 0;
+ while (mask16) {
+ if (mask16 & 1) {
+ i++;
+ }
+ mask16 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_DMA:
+ mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
+ i = 0;
+ while (mask8) {
+ if (mask8 & 1) {
+ i++;
+ }
+ mask8 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ dependFunctionCount++;
+ break;
+ case TAG_END_DEPEND:
+ dependent = FALSE;
+ alternativeListCount++;
+ break;
+ case TAG_IO_FIXED:
+ case TAG_IO:
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (!dependent) {
+ commonResCount++;
+ } else {
+ dependDescCount++;
+ }
+ break;
+ default:
+
+ //
+ // Unknown tag. Skip it.
+ //
+
+ break;
+ }
+
+ //
+ // Move to next bios resource descriptor.
+ //
+
+ buffer += increment;
+ tagName = *buffer;
+ if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ break;
+ }
+ }
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (commonResCount == 0 && dependFunctionCount == 0) {
+ *ReturnedList = NULL;
+ *ReturnedLength = 0;
+ *BiosData = buffer + 2;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Allocate memory for our internal data structures
+ //
+
+ if (dependFunctionCount) {
+ dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
+ PagedPool,
+ dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
+ dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
+ 'bPnP'
+ );
+ if (!dependResources) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ dependResList = dependResources; // remember it so we can free it.
+ }
+
+ if (alternativeListCount) {
+ ASSERT(dependFunctionCount != 0);
+ alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
+ 'bPnP'
+ );
+ if (!alternativeList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit0;
+ }
+ RtlZeroMemory(alternativeList,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
+ );
+ alternativeList[0].Resources = dependResources;
+ }
+ if (commonResCount) {
+ commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
+ PagedPool,
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
+ 'bPnP'
+ );
+ if (!commonResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit1;
+ }
+ }
+
+ //
+ // Now start over again to process the bios data and initialize our internal
+ // resource representation.
+ //
+
+ commonIoDesc = commonResources;
+ dependDescCount = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ dependent = FALSE;
+ while (tagName != TAG_COMPLETE_END) {
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ tagName &= SMALL_TAG_MASK;
+ }
+ switch (tagName) {
+ case TAG_IRQ:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_DMA:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ alternativeList[alternativeListCount].NoDependentFunctions++;
+ if (dependDescCount != 0) {
+
+ //
+ // End of current dependent function
+ //
+
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = 0;
+ dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = dependResources->Next;
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ }
+ if (*buffer & SMALL_TAG_SIZE_MASK) {
+ dependResources->Priority = *(buffer + 1);
+ }
+ dependDescCount = 0;
+ dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
+ buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
+ break;
+ case TAG_END_DEPEND:
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = DEPENDENT_FLAGS_END;
+ dependResources->Next = alternativeList[alternativeListCount].Resources;
+ dependent = FALSE;
+ dependDescCount = 0;
+ alternativeListCount++;
+ alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = alternativeList[alternativeListCount].Resources;
+ buffer++;
+ break;
+ case TAG_IO:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_IO_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ dependDescCount;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ default:
+
+ //
+ // Don't-care tag simpley advance the buffer pointer to next tag.
+ //
+
+ if (*buffer & LARGE_RESOURCE_TAG) {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ } else {
+ increment = (USHORT)(*buffer & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ }
+ buffer += increment;
+ }
+ tagName = *buffer;
+ if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ break;
+ }
+ }
+
+ if (alternativeListCount != 0) {
+ alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
+ }
+ *BiosData = buffer + 2; // Skip END_TAG
+
+ //
+ // prepare IoResourceList
+ //
+
+ noResLists = 1;
+ for (i = 0; i < alternativeListCount; i++) {
+ noResLists *= alternativeList[i].NoDependentFunctions;
+ }
+ totalDescCount = 0;
+ for (i = 0; i < alternativeListCount; i++) {
+ descCount = 1;
+ for (j = 0; j < alternativeListCount; j++) {
+ if (j == i) {
+ descCount *= alternativeList[j].TotalResourceCount;
+ } else {
+ descCount *= alternativeList[j].NoDependentFunctions;
+ }
+ }
+ totalDescCount += descCount;
+ }
+ listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
+ sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
+
+ ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
+ if (!ioResReqList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit2;
+ }
+
+ ioResReqList->ListSize = listSize;
+ ioResReqList->InterfaceType = Internal;
+ ioResReqList->BusNumber = BusNumber;
+ ioResReqList->SlotNumber = SlotNumber;
+ ioResReqList->Reserved[0] = 0;
+ ioResReqList->Reserved[1] = 0;
+ ioResReqList->Reserved[2] = 0;
+ ioResReqList->AlternativeLists = noResLists;
+ ioResList = &ioResReqList->List[0];
+
+ //
+ // Build resource lists
+ //
+
+ for (i = 0; i < noResLists; i++) {
+ ULONG size;
+ USHORT j;
+
+ ioResList->Version = 1;
+ ioResList->Revision = 0x30 | (USHORT)i;
+ buffer = (PUCHAR)&ioResList->Descriptors[0];
+
+ //
+ // Copy common resources to the list
+ //
+
+ if (commonResources) {
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
+ RtlMoveMemory(buffer, commonResources, size);
+ buffer += size;
+ }
+
+ //
+ // Copy dependent functions if any.
+ //
+
+ if (alternativeList) {
+ PbAddDependentResourcesToList(&buffer, 0, alternativeList);
+ }
+
+ //
+ // Update io resource list ptr
+ //
+
+ ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
+ sizeof(IO_RESOURCE_DESCRIPTOR);
+
+ //
+ // Hack for user mode pnp mgr
+ //
+
+ for (j = 0; j < ioResList->Count; j++) {
+ ioResList->Descriptors[j].Spare2 = j;
+ }
+ ioResList = (PIO_RESOURCE_LIST)buffer;
+ }
+
+ *ReturnedLength = listSize;
+ status = STATUS_SUCCESS;
+ *ReturnedList = ioResReqList;
+exit2:
+ if (commonResources) {
+ ExFreePool(commonResources);
+ }
+exit1:
+ if (alternativeList) {
+ ExFreePool(alternativeList);
+ }
+exit0:
+ if (dependResList) {
+ ExFreePool(dependResList);
+ }
+ return status;
+}
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds dependent functions to caller specified list.
+
+Arguments:
+
+ ResourceDescriptor - supplies a pointer to the descriptor buffer.
+
+ ListNo - supplies an index to the AlternativeList.
+
+ AlternativeList - supplies a pointer to the alternativelist array.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPB_DEPENDENT_RESOURCES dependentResources, ptr;
+ ULONG size;
+
+ //
+ // Copy dependent resources to caller supplied list buffer and
+ // update the list buffer pointer.
+ //
+
+ dependentResources = AlternativeList[ListNo].Resources;
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
+ RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
+ *ResourceDescriptor = *ResourceDescriptor + size;
+
+ //
+ // Add dependent resource of next list to caller's buffer
+ //
+
+ if (AlternativeList[ListNo + 1].Resources) {
+ ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
+ } else {
+ ptr = NULL;
+ }
+ if (ptr == NULL) {
+ AlternativeList[ListNo].Resources = dependentResources->Next;
+ if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
+ ptr = dependentResources->Next;
+ }
+ }
+ return ptr;
+}
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Arguments:
+
+ IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
+
+ CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CmDescriptor->Type = IoDescriptor->Type;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ switch (CmDescriptor->Type) {
+ case CmResourceTypePort:
+ CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
+ CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
+ break;
+ case CmResourceTypeInterrupt:
+ CmDescriptor->u.Interrupt.Level =
+ CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
+ CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
+ break;
+ case CmResourceTypeMemory:
+ CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+ CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
+ break;
+ case CmResourceTypeDma:
+ CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
+ CmDescriptor->u.Dma.Port = 0;
+ CmDescriptor->u.Dma.Reserved1 = 0;
+ break;
+ }
+}
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IRQ information to NT usable format.
+ This routine stops when an irq io resource is generated. if there are
+ more irq io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ USHORT mask;
+ ULONG irq;
+ PPNP_IRQ_DESCRIPTOR buffer;
+ UCHAR size, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ size = buffer->Tag & SMALL_TAG_SIZE_MASK;
+ mask = buffer->IrqMask;
+ mask >>= bitPosition;
+ irq = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ irq = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (irq != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeInterrupt;
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (size == 3 && buffer->Information & 0x0C) {
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ IoDescriptor->ShareDisposition = CmResourceShareShared;
+ }
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Interrupt.MinimumVector = irq;
+ IoDescriptor->u.Interrupt.MaximumVector = irq;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current irq tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ *BiosData = (PUCHAR)buffer + size + 1;
+ return status;
+}
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS DMA information to NT usable format.
+ This routine stops when an dma io resource is generated. if there are
+ more dma io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ ULONG dma;
+ PPNP_DMA_DESCRIPTOR buffer;
+ UCHAR mask, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ mask = buffer->ChannelMask;
+ mask >>= bitPosition;
+ dma = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ dma = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (dma != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeDma;
+ IoDescriptor->Flags = 0;
+ IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Dma.MinimumChannel = dma;
+ IoDescriptor->u.Dma.MaximumChannel = dma;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current dma tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return status;
+}
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS FIXED IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_FIXED_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = 1;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS MEMORY information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PUCHAR buffer;
+ UCHAR tag;
+ PHYSICAL_ADDRESS minAddr, maxAddr;
+ ULONG alignment, length;
+ USHORT increment;
+
+ buffer = *BiosData;
+ tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
+ increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
+
+ minAddr.HighPart = 0;
+ maxAddr.HighPart = 0;
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
+ maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
+ maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
+ maxAddr.LowPart = minAddr.LowPart + length - 1;
+ alignment = 1;
+ break;
+ }
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypeMemory;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Memory.MinimumAddress = minAddr;
+ IoDescriptor->u.Memory.MaximumAddress = maxAddr;
+ IoDescriptor->u.Memory.Alignment = alignment;
+ IoDescriptor->u.Memory.Length = length;
+
+ //
+ // Done with current tag, advance pointer to next tag
+ //
+
+ buffer += increment;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pnpisa.sur/data.c b/private/ntos/nthals/extender/pnpisa.sur/data.c
new file mode 100644
index 000000000..8afb53ce0
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/data.c
@@ -0,0 +1,58 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbdata.c
+
+Abstract:
+
+ Declares various data which is specific to PNP ISA bus extender architecture and
+ is independent of BIOS.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+//
+// regPNPISADeviceName
+//
+
+WCHAR rgzPNPISADeviceName[] = L"\\Device\\PnpIsa_%d";
+
+//
+// Pointers to bus extension data.
+//
+
+PI_BUS_EXTENSION PipBusExtension;
+
+//
+// Read_data_port address
+// (This is mainly for convinience. It duplicates the
+// ReadDataPort field in BUS extension structure.)
+//
+
+PUCHAR PipReadDataPort;
+PUCHAR PipCommandPort;
+PUCHAR PipAddressPort;
+
+//
+// Read data port range selection array
+//
+
+READ_DATA_PORT_RANGE
+PipReadDataPortRanges[READ_DATA_PORT_RANGE_CHOICES] =
+ {{0x274, 0x2ff, 4}, {0x374, 0x3ff, 4}, {0x338, 0x37f, 4}, {0x238, 0x27f, 4}, {0x200, 0x3ff}};
diff --git a/private/ntos/nthals/extender/pnpisa.sur/init.c b/private/ntos/nthals/extender/pnpisa.sur/init.c
new file mode 100644
index 000000000..538820af1
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/init.c
@@ -0,0 +1,620 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+ DriverEntry initialization code for pnp isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 29-Apr-1996
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+//
+// Internal References
+//
+
+PVOID
+PipGetMappedAddress(
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS IoAddress,
+ IN ULONG NumberOfBytes,
+ IN ULONG AddressSpace,
+ OUT PBOOLEAN MappedAddress
+ );
+
+NTSTATUS
+PipAcquirePortResources(
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath,
+ IN PHYSICAL_ADDRESS BaseAddressLow,
+ IN PHYSICAL_ADDRESS BaseAddressHi,
+ IN ULONG Alignment,
+ IN ULONG PortLength,
+ OUT PCM_RESOURCE_LIST *CmResourceList
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(INIT,PipAcquirePortResources)
+#pragma alloc_text(INIT,PipGetMappedAddress)
+#endif
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This is a temporary driver. It isolates all the PNP ISA cards. For each
+ Pnp Isa device, if its driver is installed, we retrieve user specified
+ resource information to configure the card and turn on the device.
+ Otherwise, we create a device instance for the device and record its resource
+ requirements list.
+
+ All the work is done in the Init/DriverEntry routine. So, this driver always
+ return failure to let itself be unloaded.
+
+Arguments:
+
+ DriverObject - specifies the driver object for the bus extender.
+
+ RegistryPath - supplies a pointer to a unicode string of the service key name in
+ the CurrentControlSet\Services key for the bus extender.
+
+Return Value:
+
+ Always return STATUS_UNSUCCESSFUL.
+
+--*/
+
+{
+ NTSTATUS status;
+ ULONG size, i, j, csn, cardDetected, maxCardDetected = 0;
+ PHYSICAL_ADDRESS baseAddrHi, baseAddrLow;
+ PUCHAR readDataPort = NULL;
+ PCM_RESOURCE_LIST cmResource, maxCmResource = NULL;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
+
+ //
+ // In the first pass, we try to isolate pnpisa cards in the machine
+ // using read data port from each predefined ranges. One some machine
+ // different number of isapnp cards can be detected. We will choose
+ // the read data port which gives the max number of pnpisa cards.
+ //
+
+ for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
+
+ baseAddrLow.LowPart = PipReadDataPortRanges[i].MinimumAddress;
+ baseAddrLow.HighPart = 0;
+ baseAddrHi.LowPart = PipReadDataPortRanges[i].MaximumAddress;
+ baseAddrHi.HighPart = 0;
+ status = PipAcquirePortResources(
+ &PipBusExtension,
+ DriverObject,
+ RegistryPath,
+ baseAddrLow,
+ baseAddrHi,
+ PipReadDataPortRanges[i].Alignment,
+ 4,
+ &cmResource
+ );
+ if (!NT_SUCCESS(status)) {
+ continue;
+ }
+
+ //
+ // Perform Pnp isolation process. This will assign card select number for each
+ // Pnp Isa card isolated by the system. All the isolated cards will be put into
+ // wait-for-key state.
+ //
+
+ PipIsolateCards(&csn);
+
+ //
+ // send initiation key to put cards into sleep state
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // For each card selected, make sure it returns valid card resource data
+ //
+
+ cardDetected = 0;
+ for (j = 1; j <= csn; j++) {
+
+ ULONG noDevices, dataLength;
+ PUCHAR cardData;
+
+ status = PipReadCardResourceData (
+ j,
+ &noDevices,
+ &cardData,
+ &dataLength);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ } else {
+ ExFreePool(cardData);
+ cardDetected++;
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ if ((cardDetected != 0) && (cardDetected >= maxCardDetected)) {
+ maxCardDetected = cardDetected;
+ readDataPort = PipReadDataPort;
+ if (maxCmResource) {
+ ExFreePool(maxCmResource);
+ }
+ maxCmResource = cmResource;
+ } else {
+ ExFreePool(cmResource);
+ }
+ }
+
+ if (readDataPort != NULL) {
+
+ if (readDataPort != PipReadDataPort) {
+ if (PipReadDataPort) {
+ if (PipBusExtension.DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort - 3, 4);
+ }
+ PipReadDataPort = NULL;
+ }
+ cmResourceDescriptor =
+ &maxCmResource->List->PartialResourceList.PartialDescriptors[0];
+ PipReadDataPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &PipBusExtension.DataPortMapped
+ );
+ if (PipReadDataPort) {
+ PipReadDataPort += 3;
+ ASSERT(readDataPort == PipReadDataPort);
+ PipBusExtension.ReadDataPort = PipReadDataPort;
+ } else {
+ goto exit;
+ }
+ }
+
+ //
+ // Perform initial bus check to find all the PnP ISA devices
+ //
+
+ PipCheckBus(&PipBusExtension);
+ ASSERT(PipBusExtension.NumberCSNs == maxCardDetected);
+
+ //
+ // Perform PnP ISA device check to see if we should enable it.
+ //
+
+ PipCheckDevices(RegistryPath, &PipBusExtension);
+
+ //
+ // Delete all the device info structures and card info structures
+ //
+
+ PipDeleteCards(&PipBusExtension);
+ }
+
+ //
+ // Release address, command and read data port resources.
+ //
+
+exit:
+ if (maxCmResource) {
+ ExFreePool(maxCmResource);
+ }
+
+ if (PipCommandPort && PipBusExtension.CmdPortMapped) {
+ MmUnmapIoSpace(PipCommandPort, 1);
+ }
+ if (PipAddressPort && PipBusExtension.AddrPortMapped) {
+ MmUnmapIoSpace(PipAddressPort, 1);
+ }
+ if (PipReadDataPort && PipBusExtension.DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort - 3, 4);
+ }
+
+ IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ NULL,
+ NULL);
+
+ //
+ // Finally, return failure to get ourself unloaded.
+ //
+
+ return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+PipAcquirePortResources(
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath,
+ IN PHYSICAL_ADDRESS BaseAddressLow,
+ IN PHYSICAL_ADDRESS BaseAddressHi,
+ IN ULONG Alignment,
+ IN ULONG PortLength,
+ OUT PCM_RESOURCE_LIST *CmResourceList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine acquires specified port resources.
+
+Arguments:
+
+ BusExtension - Supplies a pointer to the pnp bus extension.
+
+ BaseAddressLow,
+ BaseAddressHi - Supplies the read data port base address range to be mapped.
+
+ Alignment - supplies the port allignment.
+
+ PortLength = Number of ports required.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+
+{
+
+#if 1
+
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
+ NTSTATUS status;
+ ULONG size;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ ULONG i;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ *CmResourceList = NULL;
+
+ //
+ // Create a static Io resource requirements list and
+ // Call I/O mgr to get address, command and read data port addresses assigned.
+ //
+
+ size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResource = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
+ RtlZeroMemory(ioResource, size);
+ ioResource->ListSize = size;
+ ioResource->InterfaceType = Isa;
+ ioResource->AlternativeLists = 1;
+ ioResource->List[0].Version = 1;
+ ioResource->List[0].Revision = 1;
+ ioResource->List[0].Count = 1;
+ ioResource->List[0].Descriptors[0].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[0].u.Port.Length = PortLength;
+ ioResource->List[0].Descriptors[0].u.Port.Alignment = Alignment;
+ ioResource->List[0].Descriptors[0].u.Port.MinimumAddress = BaseAddressLow;
+ ioResource->List[0].Descriptors[0].u.Port.MaximumAddress = BaseAddressHi;
+
+ status = IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ ioResource,
+ &cmResource);
+ ExFreePool(ioResource);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ return status;
+ }
+
+ //
+ // Map port addr to memory addr if necessary.
+ //
+
+ if (PipAddressPort == NULL) {
+ physicalAddress.LowPart = ADDRESS_PORT;
+ physicalAddress.HighPart = 0;
+ BusExtension->AddressPort =
+ PipAddressPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ physicalAddress,
+ 1,
+ CM_RESOURCE_PORT_IO,
+ &BusExtension->AddrPortMapped
+ );
+ if (PipAddressPort == NULL) {
+ goto exit0;
+ }
+ }
+ if (PipCommandPort == NULL) {
+ physicalAddress.LowPart = COMMAND_PORT;
+ physicalAddress.HighPart = 0;
+ BusExtension->CommandPort =
+ PipCommandPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ physicalAddress,
+ 1,
+ CM_RESOURCE_PORT_IO,
+ &BusExtension->CmdPortMapped
+ );
+ if (PipCommandPort == NULL) {
+ goto exit0;
+ }
+ }
+ cmResourceDescriptor =
+ &cmResource->List->PartialResourceList.PartialDescriptors[0];
+ if ((cmResourceDescriptor->u.Port.Start.LowPart & 0xf) == 0) {
+
+ //
+ // Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
+ //
+
+ DebugPrint((DEBUG_BREAK, "PnpIsa:ReadDataPort is at yy3\n"));
+ goto exit0;
+ }
+ if (PipReadDataPort && BusExtension->DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort - 3, 4);
+ PipReadDataPort = NULL;
+ BusExtension->DataPortMapped = FALSE;
+ }
+ PipReadDataPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->DataPortMapped
+ );
+ if (PipReadDataPort) {
+ PipReadDataPort += 3;
+ PipBusExtension.ReadDataPort = PipReadDataPort;
+ }
+exit0:
+ //ExFreePool(cmResource);
+ if (PipReadDataPort && PipCommandPort && PipAddressPort) {
+ *CmResourceList = cmResource;
+ return STATUS_SUCCESS;
+ } else {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+#else
+
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDescriptor;
+ NTSTATUS status;
+ ULONG size;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ ULONG i;
+
+ //
+ // Create a static Io resource requirements list and
+ // Call I/O mgr to get address, command and read data port addresses assigned.
+ //
+
+ size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * 2;
+ ioResource = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
+ RtlZeroMemory(ioResource, size);
+ ioResource->ListSize = size;
+ ioResource->InterfaceType = Isa;
+ ioResource->AlternativeLists = 1;
+ ioResource->List[0].Version = 1;
+ ioResource->List[0].Revision = 1;
+ ioResource->List[0].Count = 3;
+ ioResource->List[0].Descriptors[0].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[0].u.Port.Length = PortLength;
+ ioResource->List[0].Descriptors[0].u.Port.Alignment = Alignment;
+ ioResource->List[0].Descriptors[0].u.Port.MinimumAddress = BaseAddressLow;
+ ioResource->List[0].Descriptors[0].u.Port.MaximumAddress = BaseAddressHi;
+ ioResource->List[0].Descriptors[1].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[1].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[1].u.Port.Length = 1;
+ ioResource->List[0].Descriptors[1].u.Port.Alignment = 1;
+ ioResource->List[0].Descriptors[1].u.Port.MinimumAddress.LowPart = ADDRESS_PORT;
+ ioResource->List[0].Descriptors[1].u.Port.MaximumAddress.LowPart = ADDRESS_PORT;
+ ioResource->List[0].Descriptors[2].Type = CmResourceTypePort;
+ ioResource->List[0].Descriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource->List[0].Descriptors[2].Flags = CM_RESOURCE_PORT_IO;
+ ioResource->List[0].Descriptors[2].u.Port.Length = 1;
+ ioResource->List[0].Descriptors[2].u.Port.Alignment = 1;
+ ioResource->List[0].Descriptors[2].u.Port.MinimumAddress.LowPart = COMMAND_PORT;
+ ioResource->List[0].Descriptors[2].u.Port.MaximumAddress.LowPart = COMMAND_PORT;
+
+ status = IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ ioResource,
+ &cmResource);
+ ExFreePool(ioResource);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ return status;
+ }
+
+ //
+ // Map port addr to memory addr if necessary.
+ //
+
+ ASSERT(cmResource->List->PartialResourceList.Count == 3);
+ for (i = 0; i < cmResource->List->PartialResourceList.Count; i++) {
+ cmResourceDescriptor =
+ &cmResource->List->PartialResourceList.PartialDescriptors[i];
+ ASSERT(cmResourceDescriptor->Type == CmResourceTypePort);
+ if (cmResourceDescriptor->u.Port.Start.LowPart == ADDRESS_PORT) {
+ if (PipAddressPort == NULL) {
+ BusExtension->AddressPort =
+ PipAddressPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->AddrPortMapped
+ );
+ }
+ } else if (cmResourceDescriptor->u.Port.Start.LowPart == COMMAND_PORT) {
+ if (PipCommandPort == NULL) {
+ BusExtension->CommandPort =
+ PipCommandPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->CmdPortMapped
+ );
+ }
+ } else {
+ if ((cmResourceDescriptor->u.Port.Start.LowPart & 0xf) == 0) {
+
+ //
+ // Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
+ //
+
+ DebugPrint((DEBUG_BREAK, "PnpIsa:ReadDataPort is at yy3\n"));
+ goto exit0;
+ }
+ if (PipReadDataPort && BusExtension->DataPortMapped) {
+ MmUnmapIoSpace(PipReadDataPort, 4);
+ PipReadDataPort = NULL;
+ BusExtension->DataPortMapped = FALSE;
+ }
+ PipReadDataPort = PipGetMappedAddress(
+ Isa, // InterfaceType
+ 0, // BusNumber,
+ cmResourceDescriptor->u.Port.Start,
+ cmResourceDescriptor->u.Port.Length,
+ cmResourceDescriptor->Flags,
+ &BusExtension->DataPortMapped
+ );
+ if (PipReadDataPort) {
+ PipReadDataPort += 3;
+ PipBusExtension.ReadDataPort = PipReadDataPort;
+ }
+ }
+ }
+exit0:
+ ExFreePool(cmResource);
+ if (PipReadDataPort && PipCommandPort && PipAddressPort) {
+ return STATUS_SUCCESS;
+ } else {
+ IoAssignResources(RegistryPath,
+ NULL,
+ DriverObject,
+ NULL,
+ NULL,
+ NULL);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+#endif // 1
+}
+
+PVOID
+PipGetMappedAddress(
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS IoAddress,
+ IN ULONG NumberOfBytes,
+ IN ULONG AddressSpace,
+ OUT PBOOLEAN MappedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps an IO address to system address space.
+
+Arguments:
+
+ BusType - Supplies the type of bus - eisa, mca, isa...
+
+ IoBusNumber - Supplies the bus number.
+
+ IoAddress - Supplies the base device address to be mapped.
+
+ NumberOfBytes - Supplies the number of bytes for which the address is
+ valid.
+
+ AddressSpace - Supplies whether the address is in io space or memory.
+
+ MappedAddress - Supplies whether the address was mapped. This only has
+ meaning if the address returned is non-null.
+
+Return Value:
+
+ The mapped address.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS cardAddress;
+ PVOID address;
+
+ HalTranslateBusAddress(BusType, BusNumber, IoAddress, &AddressSpace,
+ &cardAddress);
+
+ //
+ // Map the device base address into the virtual address space
+ // if the address is in memory space.
+ //
+
+ if (!AddressSpace) {
+
+ address = MmMapIoSpace(cardAddress, NumberOfBytes, FALSE);
+ *MappedAddress = (address ? TRUE : FALSE);
+
+ } else {
+
+ address = (PVOID) cardAddress.LowPart;
+ *MappedAddress = FALSE;
+ }
+
+ return address;
+}
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/isolate.c b/private/ntos/nthals/extender/pnpisa.sur/isolate.c
new file mode 100644
index 000000000..8e050358f
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/isolate.c
@@ -0,0 +1,1607 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ isolate.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-10-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pbios.h"
+#include "pnpisa.h"
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG Base,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ );
+
+VOID
+PipReadCardResourceDataBytes (
+ IN USHORT BytesToRead,
+ IN PUCHAR Buffer
+ );
+
+//
+// Internal type definitions
+//
+
+typedef struct _MEMORY_DESC_{
+ ULONG Base;
+ ULONG Length;
+ BOOLEAN Memory32;
+} MEMORY_DESC, *PMEMORY_DESC;
+
+typedef struct _IRQ_DESC_{
+ UCHAR Level;
+ ULONG Type;
+}IRQ_DESC, *PIRQ_DESC;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PipFindIrqInformation)
+#pragma alloc_text(INIT,PipFindMemoryInformation)
+#pragma alloc_text(INIT,PipFindIoPortInformation)
+#pragma alloc_text(INIT,PipReadCardResourceData)
+#pragma alloc_text(INIT,PipReadDeviceBootResourceData)
+#pragma alloc_text(INIT,PipWriteDeviceBootResourceData)
+#pragma alloc_text(INIT,PipLFSRInitiation)
+#pragma alloc_text(INIT,PipIsolateCards)
+#pragma alloc_text(INIT,PipFindNextLogicalDeviceTag)
+#pragma alloc_text(INIT,PipSelectLogicalDevice)
+#pragma alloc_text(INIT,PipReadCardResourceDataBytes)
+#endif
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Irq descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. On input, the BiosRequirements points to current
+ logical id tag.
+
+Arguments:
+
+ IrqLevel - Supplies the irq level.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ ULONG increment;
+ USHORT irqMask;
+ PPNP_IRQ_DESCRIPTOR biosDesc;
+
+ //
+ // Skip current logical id tag
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the Irq.
+ //
+
+ irqMask = 1 << IrqLevel;
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
+ biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->IrqMask & irqMask) {
+ if ((tag & SMALL_TAG_SIZE_MASK) == 2) {
+
+ //
+ // if no irq info is available, a value of zero is returned.
+ // (o is not a valid irq information.)
+ //
+
+ *Information = 0;
+ } else {
+ *Information = biosDesc->Information;
+ }
+ return TRUE;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG BaseAddress,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ memory descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. Note, the memory range specified by Base
+ and Limit must be within a single Pnp ISA memory descriptor.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the memory range.
+
+ Limit - Supplies the upper limit of the memory range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ NameTag - Supplies a variable to receive the Tag of the memory descriptor which
+ describes the memory information.
+
+ Information - supplies a pointer to a UCHAR to receive the memory information
+ for the specified memory range.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+
+ //
+ // Skip current logical id tag.
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the memory range described by Base and Limit.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
+ maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
+ + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
+ maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
+ + length - 1;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
+ maxAddr = minAddr + length - 1;
+ break;
+ }
+
+ if (minAddr <= BaseAddress && maxAddr >= Limit) {
+ *Information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
+ *NameTag = tag;
+ found = TRUE;
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Io port descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the Io port range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+ Alignment - supplies a pointer to a UCHAR to receive the port alignment
+ information.
+
+ RangeLength - supplies a pointer to a UCHAR to receive the port range length
+ information.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+ PPNP_PORT_DESCRIPTOR portDesc;
+ PPNP_FIXED_PORT_DESCRIPTOR fixedPortDesc;
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the io port range described by Base.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag & SMALL_TAG_MASK) {
+ case TAG_IO:
+ portDesc = (PPNP_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = portDesc->MinimumAddress;
+ maxAddr = portDesc->MaximumAddress;
+ if (minAddr <= BaseAddress && maxAddr >= BaseAddress) {
+ *Information = portDesc->Information;
+ *Alignment = portDesc->Alignment;
+ *RangeLength = portDesc->Length;
+ found = TRUE;
+ }
+ break;
+ case TAG_IO_FIXED:
+ fixedPortDesc = (PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = fixedPortDesc->MinimumAddress;
+ if (BaseAddress == minAddr) {
+ *Information = 0; // 10 bit decode
+ *Alignment = 1;
+ *RangeLength = fixedPortDesc->Length;
+ found = TRUE;
+ }
+ break;
+ }
+
+ if (found) {
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PUCHAR *ResourceData,
+ OUT PULONG ResourceDataLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads resources data from a specified PnP ISA card. It is
+ caller's responsibility to release the memory. Before calling this routine,
+ the Pnp ISA card should be in sleep state (i.e. Initiation Key was sent.)
+ After exiting this routine, the card will be left in Config state.
+
+Arguments:
+
+ Csn - Specifies the CardSelectNumber to indicate which PNP ISA card.
+
+ NumberLogicalDevices - supplies a variable to receive the number of logical devices
+ associated with the Pnp Isa card.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ ResourceDataLength - Supplies a variable to receive the length of the ResourceData.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ PUCHAR buffer, p;
+ LONG sizeToRead, limit, i;
+ USHORT size;
+ UCHAR tag;
+ ULONG noDevices;
+ BOOLEAN failed;
+
+ //
+ // Allocate memory to store the resource data.
+ // N.B. The buffer size should cover 99.999% of the machines.
+ //
+
+ sizeToRead = 4096;
+
+tryAgain:
+
+ noDevices = 0;
+ buffer = (PUCHAR)ExAllocatePoolWithTag(PagedPool, sizeToRead, 'iPnP');
+ if (!buffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Send card from sleep state to configuration state
+ // Note, by doing this the resource data includes 9 bytes Id.
+ //
+
+ PipWriteAddress (WAKE_CSN_PORT);
+ PipWriteData((UCHAR)Csn);
+
+ //
+ // Read card id bytes
+ //
+
+ p = buffer;
+ PipReadCardResourceDataBytes(NUMBER_CARD_ID_BYTES, p);
+ i = NUMBER_CARD_ID_BYTES;
+ p += NUMBER_CARD_ID_BYTES;
+
+ //
+ // read all the tag descriptors of the card resource data
+ //
+
+ failed = FALSE;
+ limit = sizeToRead - 4 - NUMBER_CARD_ID_BYTES;;
+
+ while (TRUE) {
+
+ //
+ // Read tag byte. Make sure it's a valid tag and determine
+ // the size of the descriptor.
+ //
+
+ PipReadCardResourceDataBytes(1, p);
+ tag = *p;
+ i++;
+ p++;
+ if (tag == TAG_COMPLETE_END) {
+ PipReadCardResourceDataBytes(1, p);
+ p++;
+ i++;
+ break;
+ }
+ if (tag & LARGE_RESOURCE_TAG) {
+ if (tag & 0x70) {
+ failed = TRUE;
+ break;
+ } else {
+ PipReadCardResourceDataBytes(2, p);
+ size = *((PUSHORT)p);
+ p += 2;
+ i += 2;
+ }
+ } else {
+ if ((tag & 0x70) == 0x50 || (tag & 0x70) == 0x60 || (((tag & 0x70) == 0) && (tag != 0xa))) {
+ failed = TRUE;
+ break;
+ } else {
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ noDevices++;
+ }
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ }
+ }
+
+ //
+ // read 'size' number of bytes for the current descriptor
+ //
+
+ i += size;
+ if (i < limit) {
+ PipReadCardResourceDataBytes(size, p);
+ p += size;
+ } else {
+ ExFreePool(buffer);
+ sizeToRead <<= 1; // double the buffer
+
+ //
+ // If we can find the END tag with 32K byte, assume the resource
+ // requirement list is bad.
+ //
+
+ if (sizeToRead > 0x80000) {
+ return STATUS_INVALID_PARAMETER;
+ } else {
+ goto tryAgain;
+ }
+ }
+ }
+ if (failed) {
+ ExFreePool(buffer);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Determine the real size of the buffer required and
+ // resize the buffer.
+ //
+
+ size = p - buffer; // i
+ p = (PUCHAR)ExAllocatePoolWithTag(PagedPool, size, 'iPnP');
+ if (p) {
+ RtlMoveMemory(p, buffer, size);
+ ExFreePool(buffer);
+ } else {
+
+ //
+ // Fail to resize the buffer. Simply leave it alone.
+ //
+
+ p = buffer;
+ }
+
+ //
+ // Should we leave card in config state???
+ //
+
+ *ResourceData = p;
+ *NumberLogicalDevices = noDevices;
+ *ResourceDataLength = size;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads boot resource data from an enabled logical device of a PNP ISA
+ card. Caller must put the card into configuration state and select the logical
+ device before calling this function. It is caller's responsibility to release
+ the memory. ( The boot resource data is the resources that a card assigned during
+ boot.)
+
+Arguments:
+
+ BusNumber - specifies the bus number of the device whose resource data to be read.
+
+ BiosRequirements - Supplies a pointer to the resource requirement list for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ Length - Supplies a variable to recieve the length of the resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ UCHAR c, junk1, junk2;
+ PUCHAR base;
+ ULONG l, resourceCount;
+ BOOLEAN limit;
+ LONG i, j, noMemoryDesc = 0, noIoDesc = 0, noDmaDesc =0, noIrqDesc = 0;
+ MEMORY_DESC memoryDesc[NUMBER_MEMORY_DESCRIPTORS + NUMBER_32_MEMORY_DESCRIPTORS];
+ IRQ_DESC irqDesc[NUMBER_IRQ_DESCRIPTORS];
+ UCHAR dmaDesc[NUMBER_DMA_DESCRIPTORS];
+ USHORT ioDesc[NUMBER_IO_DESCRIPTORS];
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_LIST partialResList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+
+#if 0
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DebugPrint((DEBUG_MESSAGE, "PnpIsa-ReadDeviceBootResourceData:The logical device has not been activated\n"));
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if (!BiosRequirements && ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Read memory configuration
+ //
+
+ base = (PUCHAR)ADDRESS_MEMORY_BASE;
+ for (i = 0; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+
+ //
+ // Read memory base address
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8; // l = memory base address
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8;
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ memoryDesc[noMemoryDesc].Memory32 = FALSE;
+ noMemoryDesc++;
+ base += ADDRESS_MEMORY_INCR;
+ }
+
+ //
+ // Read memory 32 configuration
+ //
+
+ for (i = 0; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+
+ base = ADDRESS_32_MEMORY_BASE(i);
+
+ //
+ // Read memory base address
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_B3; j <= ADDRESS_32_MEMORY_B0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_32_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_E3; j <= ADDRESS_32_MEMORY_E0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ memoryDesc[noMemoryDesc].Memory32 = TRUE;
+ noMemoryDesc++;
+ }
+
+ //
+ // Read Io Port Configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IO_BASE;
+ for (i = 0; i < NUMBER_IO_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IO_BASE_HI);
+ c = PipReadData();
+ l = c;
+ PipWriteAddress(base + ADDRESS_IO_BASE_LO);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ if (l == 0) {
+ break;
+ }
+ ioDesc[noIoDesc++] = (USHORT)l;
+ base += ADDRESS_IO_INCR;
+ }
+
+ //
+ // Read Interrupt configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IRQ_BASE;
+ for (i = 0; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IRQ_VALUE);
+ c = PipReadData() & 0xf;
+ if (c == 0) {
+ break;
+ }
+ irqDesc[noIrqDesc].Level = c;
+ PipWriteAddress(base + ADDRESS_IRQ_TYPE);
+ c = PipReadData();
+ irqDesc[noIrqDesc++].Type = c;
+ base += ADDRESS_IRQ_INCR;
+ }
+
+ //
+ // Read DMA configuration
+ //
+
+ base = (PUCHAR)ADDRESS_DMA_BASE;
+ for (i = 0; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_DMA_VALUE);
+ c = PipReadData() & 0x7;
+ if (c == 4) {
+ break;
+ }
+ dmaDesc[noDmaDesc++] = c;
+ base += ADDRESS_DMA_INCR;
+ }
+
+ //
+ // Construct CM_RESOURCE_LIST structure based on the resource data
+ // we collect so far.
+ //
+
+ resourceCount = noMemoryDesc + noIoDesc + noDmaDesc + noIrqDesc;
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (resourceCount == 0) {
+ *ResourceData = NULL;
+ *Length = 0;
+ return STATUS_SUCCESS;
+ }
+
+ l = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
+ ( resourceCount - 1);
+ cmResource = ExAllocatePoolWithTag(PagedPool, l, 'iPnP');
+ if (!cmResource) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(cmResource, l);
+ *Length = l; // Set returned resource data length
+ cmResource->Count = 1;
+ cmResource->List[0].InterfaceType = Isa;
+ cmResource->List[0].BusNumber = BusNumber;
+ partialResList = (PCM_PARTIAL_RESOURCE_LIST)&cmResource->List[0].PartialResourceList;
+ partialResList->Version = 0;
+ partialResList->Revision = 0x3000;
+ partialResList->Count = resourceCount;
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
+
+ //
+ // Set up all the CM memory descriptors
+ //
+
+ for (i = 0; i < noMemoryDesc; i++) {
+ partialDesc->Type = CmResourceTypeMemory;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->u.Memory.Length = memoryDesc[i].Length;
+ partialDesc->u.Memory.Start.HighPart = 0;
+ partialDesc->u.Memory.Start.LowPart = memoryDesc[i].Base;
+
+ //
+ // Need to consult configuration data for the Flags
+ //
+
+ l = memoryDesc[i].Base + memoryDesc[i].Length - 1;
+ if (PipFindMemoryInformation (memoryDesc[i].Base, l, BiosRequirements, &junk1, &c)) {
+ if (c & PNP_MEMORY_WRITE_STATUS_MASK) {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+ } else {
+ DebugPrint((DEBUG_BREAK, "PnpIsa-ReadDeviceBootResourceData:No matched memory information in config data\n"));
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+ if (memoryDesc[i].Memory32 == FALSE) {
+ partialDesc->Flags |= CM_RESOURCE_MEMORY_24;
+ }
+ partialDesc++;
+ }
+
+ //
+ // Set up all the CM io/port descriptors
+ //
+
+ for (i = 0; i < noIoDesc; i++) {
+ partialDesc->Type = CmResourceTypePort;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = CM_RESOURCE_PORT_IO;
+ partialDesc->u.Port.Start.LowPart = ioDesc[i];
+
+ //
+ // Need to consult configuration data for the Port length
+ //
+
+ if (PipFindIoPortInformation (ioDesc[i], BiosRequirements, &junk1, &junk2, &c)) {
+ partialDesc->u.Port.Length = c;
+ partialDesc++;
+ } else {
+ DebugPrint((DEBUG_BREAK, "PnpIsa-ReadDeviceBootResourceData:No matched port length in config data\n"));
+ ExFreePool(cmResource);
+ *ResourceData = NULL;
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ //
+ // Set up all the CM DMA descriptors
+ //
+
+ for (i = 0; i < noDmaDesc; i++) {
+ partialDesc->Type = CmResourceTypeDma;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = 0; // no flags for DMA descriptor
+ partialDesc->u.Dma.Channel = (ULONG) dmaDesc[i];
+ partialDesc->u.Dma.Port = 0;
+ partialDesc->u.Dma.Reserved1 = 0;
+ partialDesc++;
+ }
+
+ //
+ // Set up all the CM interrupt descriptors
+ //
+
+ for (i = 0; i < noIrqDesc; i++) {
+ partialDesc->Type = CmResourceTypeInterrupt;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (irqDesc[i].Type & 1) {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ }
+ partialDesc->u.Interrupt.Vector =
+ partialDesc->u.Interrupt.Level = irqDesc[i].Level;
+ partialDesc->u.Interrupt.Affinity = (ULONG)-1;
+ partialDesc++;
+ }
+
+ *ResourceData = cmResource;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes boot resource data to an enabled logical device of
+ a Pnp ISA card. Caller must put the card into configuration state and select
+ the logical device before calling this function.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the possible resources for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a pointer to the cm resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+ UCHAR c, information;
+ ULONG count, i, j, pass, base, limit;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
+ ULONG noIrq =0, noIo = 0, noDma = 0, noMemory = 0, no32Memory = 0;
+ PUCHAR memoryBase, irqBase, dmaBase, ioBase, tmp;
+ ULONG memory32Base;
+
+#if 0
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DbgPrint("PnpIsa-WriteDeviceBootResourceData:The logical device has not been activated\n");
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ count = CmResources->List[0].PartialResourceList.Count;
+ memoryBase = (PUCHAR)ADDRESS_MEMORY_BASE;
+ memory32Base = 0;
+ ioBase = (PUCHAR)ADDRESS_IO_BASE;
+ irqBase = (PUCHAR)ADDRESS_IRQ_BASE;
+ dmaBase = (PUCHAR)ADDRESS_DMA_BASE;
+ for (pass = 1; pass <= 2; pass++) {
+
+ //
+ // First pass we make sure the resources to be set is acceptable.
+ // Second pass we actually write the resources to the logical device's
+ // configuration space.
+ //
+
+ cmDesc = CmResources->List[0].PartialResourceList.PartialDescriptors;
+ for (i = 0; i < count; i++) {
+ switch (cmDesc->Type) {
+ case CmResourceTypePort:
+ if (pass == 1) {
+ noIo++;
+ if (noIo > NUMBER_IO_DESCRIPTORS ||
+ cmDesc->u.Port.Start.HighPart != 0 ||
+ cmDesc->u.Port.Start.LowPart & 0xffff0000 ||
+ cmDesc->u.Port.Length & 0xffffff00) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Io port base address to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Port.Start.LowPart;
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_LO);
+ PipWriteData(c);
+ c = (UCHAR)(cmDesc->u.Port.Start.LowPart >> 8);
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_HI);
+ PipWriteData(c);
+ ioBase += ADDRESS_IO_INCR;
+ }
+ break;
+ case CmResourceTypeInterrupt:
+ if (pass == 1) {
+ noIrq++;
+ if (noIrq > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Interrupt.Level & 0xfffffff0)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // See if we can get the interrupt information from possible resource
+ // data. We need it to set the configuration register.
+ //
+
+ if (!PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Irq to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Interrupt.Level;
+ PipWriteAddress(irqBase + ADDRESS_IRQ_VALUE);
+ PipWriteData(c);
+ PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information);
+ if (information != 0) {
+ switch (information & 0xf) {
+ case 1: // High true edge sensitive
+ c = 2;
+ break;
+ case 2: // Low true edge sensitive
+ c = 0;
+ break;
+ case 4: // High true level sensitive
+ c = 3;
+ break;
+ case 8: // Low true level sensitive
+ c = 1;
+ break;
+ }
+ PipWriteAddress(irqBase + ADDRESS_IRQ_TYPE);
+ PipWriteData(c);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ break;
+ case CmResourceTypeDma:
+ if (pass == 1) {
+ noDma++;
+ if (noDma > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Dma.Channel & 0xfffffff8)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Dma channel to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Dma.Channel;
+ PipWriteAddress(dmaBase + ADDRESS_DMA_VALUE);
+ PipWriteData(c);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ break;
+ case CmResourceTypeMemory:
+ if (pass == 1) {
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ if (!PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ } else {
+ if (cmDesc->Flags & CM_RESOURCE_MEMORY_24) {
+ noMemory++;
+
+ //
+ // Make sure the lower 8 bits of the base address are zero.
+ //
+
+ if (noMemory > NUMBER_MEMORY_DESCRIPTORS ||
+ base & 0xff) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+ no32Memory++;
+ if (no32Memory > NUMBER_32_MEMORY_DESCRIPTORS) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ } else {
+
+ //
+ // Find information in BiosRequirements to help determine how to write
+ // the memory configuration space.
+ //
+
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information);
+ if (cmDesc->Flags & CM_RESOURCE_MEMORY_24) {
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_LO);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_HI);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_CTL);
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT; // assume 16 bit memory
+ if (information & 0x18 == 0) { // 8 bit memory only
+ c = 0 + ADDRESS_MEMORY_CTL_LIMIT;
+ }
+ PipWriteData(c);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_LO);
+ PipWriteData((UCHAR)limit);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_HI);
+ PipWriteData((UCHAR)limit);
+ memoryBase += ADDRESS_MEMORY_INCR;
+ } else {
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B0);
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B1);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B2);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B3);
+ base >>= 8;
+ PipWriteData(base);
+ switch (information & 0x18) {
+ case 0: // 8 bit only
+ c = ADDRESS_MEMORY_CTL_LIMIT;
+ case 8: // 16 bit only
+ case 0x10: // 8 and 16 bit supported
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ case 0x18: // 32 bit only
+ c = 6 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ }
+ PipWriteAddress(ADDRESS_32_MEMORY_CTL);
+ PipWriteData(c);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E0);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E1);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E2);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E3);
+ PipWriteData(limit);
+ memory32Base++;
+ }
+ }
+ }
+ cmDesc++;
+ }
+ }
+
+ //
+ // Finally, mark all the unused descriptors as disabled.
+ //
+
+ for (i = noMemory; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+ for (j = 0; j < 5; j++) {
+ PipWriteAddress(memoryBase + j);
+ PipWriteData(0);
+ }
+ memoryBase += ADDRESS_MEMORY_INCR;
+ }
+ for (i = no32Memory; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ for (j = 0; j < 9; j++) {
+ PipWriteAddress(tmp + j);
+ PipWriteData(0);
+ }
+ memory32Base++;
+ }
+ for (i = noIo; i < NUMBER_IO_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(ioBase + j);
+ PipWriteData(0);
+ }
+ ioBase += ADDRESS_IO_INCR;
+ }
+ for (i = noIrq; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(irqBase + j);
+ PipWriteData(0);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ for (i = noDma; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(dmaBase);
+ PipWriteData(4);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ return STATUS_SUCCESS;
+}
+
+VOID
+PipLFSRInitiation (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insures the LFSR (linear feedback shift register) is in its
+ initial state and then performs 32 writes to the ADDRESS port to initiation
+ LFSR function.
+
+ Pnp software sends the initiation key to all the Pnp ISA cards to place them
+ into configuration mode. The software then ready to perform isolation
+ protocol.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR seed, bit7;
+ ULONG i;
+
+ //
+ // First perform two writes of value zero to insure the LFSR is in the
+ // initial state.
+ //
+
+ PipWriteAddress (0);
+ PipWriteAddress (0);
+
+ //
+ // Perform the initiation key.
+ //
+
+ seed = LFSR_SEED; // initial value of 0x6a
+ for (i = 0; i < 32; i++) {
+ PipWriteAddress (seed);
+ bit7=(((seed & 2) >> 1) ^ (seed & 1)) << 7;
+ seed =(seed >> 1) | bit7;
+ }
+}
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs PnP ISA cards isolation sequence.
+
+Arguments:
+
+ NumberCSNs - supplies the addr of a variable to receive the number of
+ Pnp Isa cards isolated.
+
+ ReadDataPort - Supplies the address of a variable to supply ReadData port
+ address.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT j, i;
+ UCHAR cardId[NUMBER_CARD_ID_BYTES];
+ UCHAR bit, bit7, checksum, byte1, byte2;
+ ULONG csn = 0;
+
+ *NumberCSNs = 0;
+
+ //
+ // First send Initiation Key to all the PNP ISA cards to enable PnP auto-config
+ // ports and put all cards in configuration mode.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Reset all Pnp ISA cards' CSN to 0 and return to wait-for-key state
+ //
+
+ PipWriteAddress (CONFIG_CONTROL_PORT);
+ PipWriteData (CONTROL_WAIT_FOR_KEY | CONTROL_RESET_CSN);
+
+ //
+ // Delay 2 msec for cards to load initial configuration state.
+ //
+
+ KeStallExecutionProcessor(20000); // delay 2 msec
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ // The hardware on each PnP Isa card expects 72 pairs of I/O read
+ // access to the read data port.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Starting Pnp Isa card isolation process.
+ //
+
+ //
+ // Send WAKE[CSN=0] to force all cards without CSN into isolation
+ // state to set READ DATA PORT.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ //
+ // Set read data port to current testing value.
+ //
+
+ PipWriteAddress(SET_READ_DATA_PORT);
+ PipWriteData((UCHAR)((ULONG)PipReadDataPort >> 2));
+
+ //
+ // Isolate one PnP ISA card until fail
+ //
+
+ while (TRUE) {
+
+ //
+ // Read serial isolation port to cause PnP cards in the isolation
+ // state to compare one bit of the boards ID.
+ //
+
+ PipWriteAddress(SERIAL_ISOLATION_PORT);
+
+ //
+ // We need to delay 1 msec prior to starting the first pair of isolation
+ // reads and must wait 250usec between each subsequent pair of isolation
+ // reads. This delay gives the ISA cards time to access information from
+ // possible very slow storage device.
+ //
+
+ KeStallExecutionProcessor(10000); // delay 1 msec
+
+ RtlZeroMemory(cardId, NUMBER_CARD_ID_BYTES);
+ checksum = LFSR_SEED;
+ for (j = 0; j < NUMBER_CARD_ID_BITS; j++) {
+
+ //
+ // Read card id bit by bit
+ //
+
+ byte1 = PipReadData();
+ byte2 = PipReadData();
+ bit = (byte1 == ISOLATION_TEST_BYTE_1) && (byte2 == ISOLATION_TEST_BYTE_2);
+ cardId[j / 8] |= bit << (j % 8);
+ if (j < CHECKSUMED_BITS) {
+
+ //
+ // Calculate checksum and only do it for the first 64 bits
+ //
+
+ bit7 = (((checksum & 2) >> 1) ^ (checksum & 1) ^ (bit)) << 7;
+ checksum = (checksum >> 1) | bit7;
+ }
+ KeStallExecutionProcessor(2500); // delay 250 usec
+ }
+
+ //
+ // Verify the card id we read is legitimate
+ // First make sure checksum is valid. Note zero checksum is considered valid.
+ //
+
+ if (cardId[8] == 0 || checksum == cardId[8]) {
+
+ //
+ // Next make sure cardId is not zero
+ //
+
+ byte1 = 0;
+ for (j = 0; j < NUMBER_CARD_ID_BYTES; j++) {
+ byte1 |= cardId[j];
+ }
+ if (byte1 != 0) {
+
+ //
+ // We found a valid Pnp Isa card, assign it a CSN number
+ //
+
+ PipWriteAddress(SET_CSN_PORT);
+
+ PipWriteData(++csn);
+
+ //
+ // Do Wake[CSN] command to put the newly isolated card to
+ // sleep state and other un-isolated cards to isolation
+ // state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ continue; // ... to isolate more cards ...
+ }
+ }
+ break; // could not isolate more cards ...
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+ *NumberCSNs = csn;
+}
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ )
+
+/*++
+
+Routine Description:
+
+ This function searches the Pnp Isa card data for the Next logical
+ device tag encountered. The input *CardData should point to an logical device id tag,
+ which is the current logical device tag. If the *CardData does not point to a logical
+ device id tag (but, it must point to some kind of tag), it will be moved to next
+ logical device id tag.
+
+Arguments:
+
+ CardData - a variable to supply a pointer to the pnp Isa resource descriptors and to
+ receive next logical device tag pointer.
+
+ Limit - a variable to supply the maximum length of the search and to receive the new
+ lemit after the search.
+
+Return Value:
+
+ Length of the data between current and next logical device tags, ie the data length
+ of the current logical device.
+ In case there is no 'next' logical device tag, the returned *CardData = NULL,
+ *Limit = zero and the data length of current logical tag is returned as function
+ returned value.
+
+--*/
+{
+ UCHAR tag;
+ USHORT size;
+ LONG l;
+ ULONG retLength;
+ PUCHAR p;
+ BOOLEAN atIdTag = FALSE;;
+
+ p = *CardData;
+ l = *Limit;
+ tag = *p;
+ retLength = 0;
+ while (tag != TAG_COMPLETE_END && l > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *((PUSHORT)(p + 1));
+ size += 3; // length of large tag
+ }
+
+ p += size;
+ retLength += size;
+ l -= size;
+ tag = *p;
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ *CardData = p;
+ *Limit = l;
+ return retLength;
+ }
+ }
+ *CardData = NULL;
+ *Limit = 0;
+ if (tag == TAG_COMPLETE_END) {
+ return (retLength + 2); // add 2 for the length of end tag descriptor
+ } else {
+ return 0;
+ }
+}
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber,
+ IN BOOLEAN Activate
+ )
+
+/*++
+
+Routine Description:
+
+ This function selects the logical logical device in the specified device.
+
+Arguments:
+
+ Csn - Supplies a CardSelectNumber to select the card.
+
+ LogicalDeviceNumber - supplies a logical device number to select the logical device.
+
+ Activate - supplies a BOOLEAN variable to specify if the logical device should be
+ enabled.
+
+Return Value:
+
+ None
+--*/
+{
+ UCHAR tmp;
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Send WAKE[CSN] to force the card into config state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(Csn);
+
+ //
+ // Select the logical device.
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(LogicalDeviceNumber);
+ if (Activate) {
+
+ //
+ // If we need to activate the logical device, disable its io range check and
+ // then enable the device.
+ //
+
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+ PipWriteAddress(ACTIVATE_PORT);
+ PipWriteData(1);
+ }
+}
+
+VOID
+PipReadCardResourceDataBytes (
+ IN USHORT BytesToRead,
+ IN PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads specified number of bytes of card resource data .
+
+Arguments:
+
+ BytesToRead - supplies number of bytes to read.
+
+ Buffer - supplies a pointer to a buffer to receive the read bytes.
+
+Return Value:
+
+ None
+--*/
+{
+ USHORT i;
+ PUCHAR p;
+
+ for (i = 0, p = Buffer; i < BytesToRead; i++, p++) {
+
+ PipWriteAddress(CONFIG_DATA_STATUS_PORT);
+
+ //
+ // Waiting for data ready status bit
+ //
+
+ while ((PipReadData() & 1) != 1) {
+ }
+
+ //
+ // Read the data ...
+ //
+
+ PipWriteAddress(CONFIG_DATA_PORT);
+ *p = PipReadData();
+ }
+
+}
diff --git a/private/ntos/nthals/extender/pnpisa.sur/makefile b/private/ntos/nthals/extender/pnpisa.sur/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/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/pnpisa.sur/misc.c b/private/ntos/nthals/extender/pnpisa.sur/misc.c
new file mode 100644
index 000000000..df32be4a8
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/misc.c
@@ -0,0 +1,1258 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+ This file contains pnp isa bus extender support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 27-Jusly-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,PipDecompressEisaId)
+#pragma alloc_text(INIT,PipOpenRegistryKey)
+#pragma alloc_text(INIT,PipOpenRegistryKeyPersist)
+#pragma alloc_text(INIT,PipGetRegistryValue)
+#pragma alloc_text(INIT,PipOpenCurrentHwProfileDeviceInstanceKey)
+#pragma alloc_text(INIT,PipGetDeviceInstanceCsConfigFlags)
+#pragma alloc_text(INIT,PipRemoveStringFromValueKey)
+#pragma alloc_text(INIT,PipAppendStringToValueKey)
+#pragma alloc_text(INIT,PipServiceInstanceToDeviceInstance)
+#if DBG
+#pragma alloc_text(INIT,PipDebugPrint)
+#pragma alloc_text(INIT,PipDumpIoResourceDescriptor)
+#pragma alloc_text(INIT,PipDumpIoResourceList)
+#pragma alloc_text(INIT,PipDumpCmResourceDescriptor)
+#pragma alloc_text(INIT,PipDumpCmResourceList)
+#endif
+#endif
+
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decompressed compressed Eisa Id and returns the Id to caller
+ specified character buffer.
+
+Arguments:
+
+ CompressedId - supplies the compressed Eisa Id.
+
+ EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT c1, c2;
+ LONG i;
+
+ PAGED_CODE();
+
+ CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
+ c1 = c2 = (USHORT)CompressedId;
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ for (i = 2; i >= 0; i--) {
+ *(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
+ c1 >>= 5;
+ }
+ EisaId += 3;
+ c1 = c2 = (USHORT)(CompressedId >> 16);
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ sprintf (EisaId, "%04x", c1);
+}
+
+NTSTATUS
+PipOpenRegistryKey(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create
+ )
+
+/*++
+
+Routine Description:
+
+ Opens or creates a VOLATILE registry key using the name passed in based
+ at the BaseHandle node.
+
+Arguments:
+
+ Handle - Pointer to the handle which will contain the registry key that
+ was opened.
+
+ BaseHandle - Handle to the base path from which the key must be opened.
+
+ KeyName - Name of the Key that must be opened/created.
+
+ DesiredAccess - Specifies the desired access that the caller needs to
+ the key.
+
+ Create - Determines if the key is to be created if it does not exist.
+
+Return Value:
+
+ The function value is the final status of the operation.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ ULONG disposition;
+
+ PAGED_CODE();
+
+ //
+ // Initialize the object for the key.
+ //
+
+ InitializeObjectAttributes( &objectAttributes,
+ KeyName,
+ OBJ_CASE_INSENSITIVE,
+ BaseHandle,
+ (PSECURITY_DESCRIPTOR) NULL );
+
+ //
+ // Create the key or open it, as appropriate based on the caller's
+ // wishes.
+ //
+
+ if (Create) {
+ return ZwCreateKey( Handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ } else {
+ return ZwOpenKey( Handle,
+ DesiredAccess,
+ &objectAttributes );
+ }
+}
+NTSTATUS
+PipOpenRegistryKeyPersist(
+ OUT PHANDLE Handle,
+ IN HANDLE BaseHandle OPTIONAL,
+ IN PUNICODE_STRING KeyName,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN Create,
+ OUT PULONG Disposition OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ Opens or creates a PERSIST (non-volatile) registry key using the name
+ passed in based at the BaseHandle node. This name may specify a key
+ that is actually a registry path, in which case each intermediate subkey
+ will be created (if Create is TRUE).
+
+ NOTE: Creating a registry path (i.e., more than one of the keys in the path
+ do not presently exist) requires that a BaseHandle be specified.
+
+Arguments:
+
+ Handle - Pointer to the handle which will contain the registry key that
+ was opened.
+
+ BaseHandle - Optional handle to the base path from which the key must be opened.
+ If KeyName specifies a registry path that must be created, then this parameter
+ must be specified, and KeyName must be a relative path.
+
+ KeyName - Name of the Key that must be opened/created (possibly a registry path)
+
+ DesiredAccess - Specifies the desired access that the caller needs to
+ the key.
+
+ Create - Determines if the key is to be created if it does not exist.
+
+ Disposition - If Create is TRUE, this optional pointer receives a ULONG indicating
+ whether the key was newly created:
+
+ REG_CREATED_NEW_KEY - A new Registry Key was created
+ REG_OPENED_EXISTING_KEY - An existing Registry Key was opened
+
+Return Value:
+
+ The function value is the final status of the operation.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ ULONG disposition, baseHandleIndex = 0, keyHandleIndex = 1, closeBaseHandle;
+ HANDLE handles[2];
+ BOOLEAN continueParsing;
+ PWCHAR pathEndPtr, pathCurPtr, pathBeginPtr;
+ ULONG pathComponentLength;
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ InitializeObjectAttributes(&objectAttributes,
+ KeyName,
+ OBJ_CASE_INSENSITIVE,
+ BaseHandle,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+ if(Create) {
+ //
+ // Attempt to create the path as specified. We have to try it this
+ // way first, because it allows us to create a key without a BaseHandle
+ // (if only the last component of the registry path is not present).
+ //
+ status = ZwCreateKey(&(handles[keyHandleIndex]),
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition
+ );
+
+ if(!((status == STATUS_OBJECT_NAME_NOT_FOUND) && ARGUMENT_PRESENT(BaseHandle))) {
+ //
+ // Then either we succeeded, or failed, but there's nothing we can do
+ // about it. In either case, prepare to return.
+ //
+ goto PrepareForReturn;
+ }
+
+ } else {
+ //
+ // Simply attempt to open the path, as specified.
+ //
+ return ZwOpenKey(Handle,
+ DesiredAccess,
+ &objectAttributes
+ );
+ }
+
+ //
+ // If we get to here, then there must be more than one element of the
+ // registry path that does not currently exist. We will now parse the
+ // specified path, extracting each component and doing a ZwCreateKey on it.
+ //
+ handles[baseHandleIndex] = NULL;
+ handles[keyHandleIndex] = BaseHandle;
+ closeBaseHandle = 0;
+ continueParsing = TRUE;
+ pathBeginPtr = KeyName->Buffer;
+ pathEndPtr = (PWCHAR)((PCHAR)pathBeginPtr + KeyName->Length);
+ status = STATUS_SUCCESS;
+
+ while(continueParsing) {
+ //
+ // There's more to do, so close the previous base handle (if necessary),
+ // and replace it with the current key handle.
+ //
+ if(closeBaseHandle > 1) {
+ ZwClose(handles[baseHandleIndex]);
+ }
+ baseHandleIndex = keyHandleIndex;
+ keyHandleIndex = (keyHandleIndex + 1) & 1; // toggle between 0 and 1.
+ handles[keyHandleIndex] = NULL;
+
+ //
+ // Extract next component out of the specified registry path.
+ //
+ for(pathCurPtr = pathBeginPtr;
+ ((pathCurPtr < pathEndPtr) && (*pathCurPtr != OBJ_NAME_PATH_SEPARATOR));
+ pathCurPtr++);
+
+ if (pathComponentLength = (PCHAR)pathCurPtr - (PCHAR)pathBeginPtr) {
+ //
+ // Then we have a non-empty path component (key name). Attempt
+ // to create this key.
+ //
+ unicodeString.Buffer = pathBeginPtr;
+ unicodeString.Length = unicodeString.MaximumLength = (USHORT)pathComponentLength;
+
+ InitializeObjectAttributes(&objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ handles[baseHandleIndex],
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+ status = ZwCreateKey(&(handles[keyHandleIndex]),
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_NON_VOLATILE,
+ &disposition
+ );
+ if (NT_SUCCESS(status)) {
+ //
+ // Increment the closeBaseHandle value, which basically tells us whether
+ // the BaseHandle passed in has been 'shifted out' of our way, so that
+ // we should start closing our base handles when we're finished with them.
+ //
+ closeBaseHandle++;
+ } else {
+ continueParsing = FALSE;
+ continue;
+ }
+ } else {
+ //
+ // Either a path separator ('\') was included at the beginning of
+ // the path, or we hit 2 consecutive separators.
+ //
+ status = STATUS_INVALID_PARAMETER;
+ continueParsing = FALSE;
+ continue;
+ }
+
+ if ((pathCurPtr == pathEndPtr) ||
+ ((pathBeginPtr = pathCurPtr + 1) == pathEndPtr)) {
+ //
+ // Then we've reached the end of the path
+ //
+ continueParsing = FALSE;
+ }
+ }
+
+ if (closeBaseHandle > 1) {
+ ZwClose(handles[baseHandleIndex]);
+ }
+
+PrepareForReturn:
+
+ if (NT_SUCCESS(status)) {
+ *Handle = handles[keyHandleIndex];
+
+ if(ARGUMENT_PRESENT(Disposition)) {
+ *Disposition = disposition;
+ }
+ }
+
+ return status;
+}
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to retrieve the data for a registry key's value.
+ This is done by querying the value of the key with a zero-length buffer
+ to determine the size of the value, and then allocating a buffer and
+ actually querying the value into the buffer.
+
+ It is the responsibility of the caller to free the buffer.
+
+Arguments:
+
+ KeyHandle - Supplies the key handle whose value is to be queried
+
+ ValueName - Supplies the null-terminated Unicode name of the value.
+
+ Information - Returns a pointer to the allocated data buffer.
+
+Return Value:
+
+ The function value is the final status of the query operation.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PKEY_VALUE_FULL_INFORMATION infoBuffer;
+ ULONG keyValueLength;
+
+ PAGED_CODE();
+
+ *Information = NULL;
+ RtlInitUnicodeString( &unicodeString, ValueName );
+
+ //
+ // Figure out how big the data value is so that a buffer of the
+ // appropriate size can be allocated.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ (PVOID) NULL,
+ 0,
+ &keyValueLength );
+ if (status != STATUS_BUFFER_OVERFLOW &&
+ status != STATUS_BUFFER_TOO_SMALL) {
+ return status;
+ }
+
+ //
+ // Allocate a buffer large enough to contain the entire key data value.
+ //
+
+ infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
+ if (!infoBuffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Query the data for the key value.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ infoBuffer,
+ keyValueLength,
+ &keyValueLength );
+ if (!NT_SUCCESS( status )) {
+ ExFreePool( infoBuffer );
+ return status;
+ }
+
+ //
+ // Everything worked, so simply return the address of the allocated
+ // buffer to the caller, who is now responsible for freeing it.
+ //
+
+ *Information = infoBuffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipOpenCurrentHwProfileDeviceInstanceKey(
+ OUT PHANDLE Handle,
+ IN PUNICODE_STRING DeviceInstanceName,
+ IN ACCESS_MASK DesiredAccess
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the csconfig flags for the specified device
+ which is specified by the instance number under ServiceKeyName\Enum.
+
+Arguments:
+
+ ServiceKeyName - Supplies a pointer to the name of the subkey in the
+ system service list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
+ that caused the driver to load. This is the RegistryPath parameter
+ to the DriverEntry routine.
+
+ Instance - Supplies the instance value under ServiceKeyName\Enum key
+
+ DesiredAccess - Specifies the desired access that the caller needs to
+ the key.
+
+ Create - Determines if the key is to be created if it does not exist.
+
+Return Value:
+
+ status
+
+--*/
+
+{
+ NTSTATUS status;
+ UNICODE_STRING unicodeString;
+ HANDLE profileEnumHandle;
+
+ //
+ // See if we can open the device instance key of current hardware profile
+ //
+ RtlInitUnicodeString (
+ &unicodeString,
+ L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT\\SYSTEM\\CURRENTCONTROLSET\\ENUM"
+ );
+ status = PipOpenRegistryKey(&profileEnumHandle,
+ NULL,
+ &unicodeString,
+ KEY_READ,
+ FALSE
+ );
+ if (NT_SUCCESS(status)) {
+ status = PipOpenRegistryKey(Handle,
+ profileEnumHandle,
+ DeviceInstanceName,
+ DesiredAccess,
+ FALSE
+ );
+ ZwClose(profileEnumHandle);
+ }
+ return status;
+}
+
+NTSTATUS
+PipGetDeviceInstanceCsConfigFlags(
+ IN PUNICODE_STRING DeviceInstance,
+ OUT PULONG CsConfigFlags
+ )
+
+/*++
+
+Routine Description:
+
+ This routine retrieves the csconfig flags for the specified device
+ which is specified by the instance number under ServiceKeyName\Enum.
+
+Arguments:
+
+ ServiceKeyName - Supplies a pointer to the name of the subkey in the
+ system service list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
+ that caused the driver to load.
+
+// Instance - Supplies the instance value under ServiceKeyName\Enum key
+//
+ CsConfigFlags - Supplies a variable to receive the device's CsConfigFlags
+
+Return Value:
+
+ status
+
+--*/
+
+{
+ NTSTATUS status;
+ HANDLE handle;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+
+ *CsConfigFlags = 0;
+
+ status = PipOpenCurrentHwProfileDeviceInstanceKey(&handle,
+ DeviceInstance,
+ KEY_READ
+ );
+ if(NT_SUCCESS(status)) {
+ status = PipGetRegistryValue(handle,
+ L"CsConfigFlags",
+ &keyValueInformation
+ );
+ if(NT_SUCCESS(status)) {
+ if((keyValueInformation->Type == REG_DWORD) &&
+ (keyValueInformation->DataLength >= sizeof(ULONG))) {
+ *CsConfigFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
+ }
+ ExFreePool(keyValueInformation);
+ }
+ ZwClose(handle);
+ }
+ return status;
+}
+
+NTSTATUS
+PipRemoveStringFromValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine remove a string from a value entry specified by ValueName
+ under an already opened registry handle. Note, this routine will not
+ delete the ValueName entry even it becomes empty after the removal.
+
+Parameters:
+
+ Handle - Supplies the handle to a registry key whose value entry will
+ be modified.
+
+ ValueName - Supplies a unicode string to specify the value entry.
+
+ String - Supplies a unicode string to remove from value entry.
+
+Return Value:
+
+ Status code that indicates whether or not the function was successful.
+
+--*/
+
+{
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ UNICODE_STRING unicodeString;
+ PWSTR nextString, currentString;
+ ULONG length, leftLength;
+ NTSTATUS status;
+ BOOLEAN found = FALSE;
+
+ if (String == NULL || String->Length / sizeof(WCHAR) == 0) {
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Read registry value entry data
+ //
+
+ status = PipGetRegistryValue(Handle, ValueName, &keyValueInformation);
+
+ if (!NT_SUCCESS( status )) {
+ return status;
+ } else if ((keyValueInformation->Type != REG_MULTI_SZ) ||
+ (keyValueInformation->DataLength == 0)) {
+
+ ExFreePool(keyValueInformation);
+ return (keyValueInformation->Type == REG_MULTI_SZ) ? STATUS_SUCCESS
+ : STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Scan through the multi_sz string to find the matching string
+ // and remove it.
+ //
+
+ status = STATUS_SUCCESS;
+ currentString = (PWSTR)KEY_VALUE_DATA(keyValueInformation);
+ leftLength = keyValueInformation->DataLength;
+ while (!found && leftLength >= String->Length + sizeof(WCHAR)) {
+ unicodeString.Buffer = currentString;
+ length = wcslen( currentString ) * sizeof( WCHAR );
+ unicodeString.Length = (USHORT)length;
+ length += sizeof(UNICODE_NULL);
+ unicodeString.MaximumLength = (USHORT)length;
+ nextString = currentString + length / sizeof(WCHAR);
+ leftLength -= length;
+
+ if (RtlEqualUnicodeString(&unicodeString, String, TRUE)) {
+ found = TRUE;
+ RtlMoveMemory(currentString, nextString, leftLength);
+ RtlInitUnicodeString(&unicodeString, ValueName);
+ status = ZwSetValueKey(
+ Handle,
+ &unicodeString,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ KEY_VALUE_DATA(keyValueInformation),
+ keyValueInformation->DataLength - length
+ );
+ break;
+ } else {
+ currentString = nextString;
+ }
+ }
+ ExFreePool(keyValueInformation);
+ return status;
+}
+
+NTSTATUS
+PipAppendStringToValueKey (
+ IN HANDLE Handle,
+ IN PWSTR ValueName,
+ IN PUNICODE_STRING String,
+ IN BOOLEAN Create
+ )
+
+/*++
+
+Routine Description:
+
+ This routine appends a string to a value entry specified by ValueName
+ under an already opened registry handle. If the ValueName is not present
+ and Create is TRUE, a new value entry will be created using the name
+ ValueName.
+
+Parameters:
+
+ Handle - Supplies the handle to a registry key whose value entry will
+ be modified.
+
+ ValueName - Supplies a pointer to a string to specify the value entry.
+
+ String - Supplies a unicode string to append to the value entry.
+
+ Create - Supplies a BOOLEAN variable to indicate if the ValueName
+ value entry should be created if it is not present.
+
+Return Value:
+
+ Status code that indicates whether or not the function was successful.
+
+--*/
+
+{
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ PWSTR destinationString, p;
+ UNICODE_STRING unicodeValueName;
+ ULONG size;
+ NTSTATUS status;
+
+ if ( !String || (String->Length < sizeof(WCHAR)) ) {
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Read registry value entry data
+ //
+
+ status = PipGetRegistryValue(Handle, ValueName, &keyValueInformation);
+
+ if(!NT_SUCCESS( status )) {
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND && Create) {
+
+ //
+ // if no valid entry exists and user said ok to create one
+ //
+
+ keyValueInformation = NULL;
+ } else {
+ return status;
+ }
+ } else if(keyValueInformation->Type != REG_MULTI_SZ) {
+
+ ExFreePool(keyValueInformation);
+
+ if(Create) {
+ keyValueInformation = NULL;
+ } else {
+ return STATUS_INVALID_PARAMETER_2;
+ }
+
+ } else if(keyValueInformation->DataLength < sizeof(WCHAR)) {
+
+ ExFreePool(keyValueInformation);
+ keyValueInformation = NULL;
+ }
+
+ //
+ // Allocate a buffer to hold new data for the specified key value entry
+ // Make sure the buffer is at least an empty MULTI_SZ big.
+ //
+
+ if (keyValueInformation) {
+ size = keyValueInformation->DataLength + String->Length + sizeof (UNICODE_NULL);
+ } else {
+ size = String->Length + 2 * sizeof(UNICODE_NULL);
+ }
+
+ destinationString = p = (PWSTR)ExAllocatePool(PagedPool, size);
+ if (destinationString == NULL) {
+ if (keyValueInformation) {
+ ExFreePool(keyValueInformation);
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Copy the existing data to our newly allocated buffer, if any
+ //
+
+ if (keyValueInformation) {
+
+ //
+ // Note we need to remove a UNICODE_NULL because the
+ // MULTI_SZ has two terminating UNICODE_NULL.
+ //
+
+ RtlMoveMemory(p,
+ KEY_VALUE_DATA(keyValueInformation),
+ keyValueInformation->DataLength - sizeof(WCHAR)
+ );
+ p += keyValueInformation->DataLength / sizeof(WCHAR) - 1;
+
+ ExFreePool(keyValueInformation);
+ }
+
+ //
+ // Append the user specified unicode string to our buffer
+ //
+ RtlMoveMemory(p,
+ String->Buffer,
+ String->Length
+ );
+ p += String->Length / sizeof(WCHAR);
+ *p = UNICODE_NULL;
+ p++;
+ *p = UNICODE_NULL;
+
+ //
+ // Finally write the data to the specified registy value entry
+ //
+
+ RtlInitUnicodeString(&unicodeValueName, ValueName);
+ status = ZwSetValueKey(
+ Handle,
+ &unicodeValueName,
+ TITLE_INDEX_VALUE,
+ REG_MULTI_SZ,
+ destinationString,
+ size
+ );
+
+ ExFreePool(destinationString);
+ return status;
+}
+
+NTSTATUS
+PipServiceInstanceToDeviceInstance (
+ IN PUNICODE_STRING RegistryPath,
+ IN ULONG ServiceInstanceOrdinal,
+ OUT PUNICODE_STRING DeviceInstanceRegistryPath OPTIONAL,
+ OUT PHANDLE DeviceInstanceHandle OPTIONAL,
+ IN ACCESS_MASK DesiredAccess
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the service node enum entry to find the desired device instance
+ under the System\Enum tree. It then optionally returns the registry path of the
+ specified device instance (relative to HKLM\System\Enum) and an open handle
+ to that registry key.
+
+ It is the caller's responsibility to close the handle returned if
+ DeviceInstanceHandle is supplied, and also to free the (PagedPool) memory
+ allocated for the unicode string buffer of DeviceInstanceRegistryPath, if
+ supplied.
+
+Parameters:
+
+ RegistryPath - Supplies the name of the service entry that controls
+ the device instance. This is the registry path passed to DriverEntry.
+
+ ServiceInstanceOrdinal - Supplies the instance value under the service entry's
+ volatile Enum subkey that references the desired device instance.
+
+ DeviceInstanceRegistryPath - Optionally, supplies a pointer to a unicode string
+ that will be initialized with the registry path (relative to HKLM\System\Enum)
+ to the device instance key.
+
+ DeviceInstanceHandle - Optionally, supplies a pointer to a variable that will
+ receive a handle to the opened device instance registry key.
+
+ DesiredAccess - If DeviceInstanceHandle is specified (i.e., the device instance
+ key is to be opened), then this variable specifies the access that is needed
+ to this key.
+
+Return Value:
+
+ NT status code indicating whether the function was successful.
+
+--*/
+
+{
+ WCHAR unicodeBuffer[20];
+ UNICODE_STRING unicodeKeyName, unicodeString;
+ NTSTATUS status;
+ HANDLE handle, handlex;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+ PWSTR buffer;
+
+ //
+ // Open registry ServiceKeyName\Enum branch
+ //
+
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ RegistryPath,
+ KEY_ALL_ACCESS,
+ FALSE
+ );
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE, "PnPIsa: Unable to open Service RegistryPath\n"));
+ return status;
+ }
+
+ RtlInitUnicodeString(&unicodeKeyName, L"ENUM");
+ status = PipOpenRegistryKey(&handlex,
+ handle,
+ &unicodeKeyName,
+ KEY_READ,
+ FALSE
+ );
+ ZwClose(handle);
+ if (!NT_SUCCESS( status )) {
+
+ //
+ // There is no registry key for the ServiceKeyName\Enum information.
+ //
+
+ return status;
+ }
+
+ //
+ // Read a path to System\Enum hardware tree branch specified by the service
+ // instance ordinal
+ //
+
+ swprintf(unicodeBuffer, L"%u", ServiceInstanceOrdinal);
+ status = PipGetRegistryValue ( handlex,
+ unicodeBuffer,
+ &keyValueInformation
+ );
+
+ ZwClose(handlex);
+ if (!NT_SUCCESS( status )) {
+ return status;
+ } else {
+ if (keyValueInformation->Type == REG_SZ) {
+ unicodeKeyName.Buffer = (PWSTR)KEY_VALUE_DATA(keyValueInformation);
+ unicodeKeyName.MaximumLength = (USHORT)keyValueInformation->DataLength;
+ unicodeKeyName.Length = unicodeKeyName.MaximumLength - sizeof(UNICODE_NULL);
+ if(!unicodeKeyName.Length) {
+ status = STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ } else {
+ status = STATUS_INVALID_PLUGPLAY_DEVICE_PATH;
+ }
+
+ if(!NT_SUCCESS(status)) {
+ goto PrepareForReturn;
+ }
+ }
+
+ //
+ // If the DeviceInstanceHandle argument was specified, open the device instance
+ // key under HKLM\System\CurrentControlSet\Enum
+ //
+
+ if (ARGUMENT_PRESENT(DeviceInstanceHandle)) {
+ RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
+ status = PipOpenRegistryKey(&handle,
+ NULL,
+ &unicodeString,
+ KEY_READ,
+ FALSE
+ );
+
+ if (NT_SUCCESS( status )) {
+
+ status = PipOpenRegistryKey (DeviceInstanceHandle,
+ handle,
+ &unicodeKeyName,
+ DesiredAccess,
+ FALSE
+ );
+ ZwClose(handle);
+ }
+
+ if (!NT_SUCCESS( status )) {
+ goto PrepareForReturn;
+ }
+ }
+
+ //
+ // If the DeviceInstanceRegistryPath argument was specified, then store a
+ // copy of the device instance path in the supplied unicode string variable.
+ //
+
+ if (ARGUMENT_PRESENT(DeviceInstanceRegistryPath)) {
+
+ buffer = (PWSTR)ExAllocatePool(PagedPool, unicodeKeyName.MaximumLength);
+ if (!buffer) {
+ if(ARGUMENT_PRESENT(DeviceInstanceHandle)) {
+ ZwClose(*DeviceInstanceHandle);
+ }
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ RtlMoveMemory(buffer, unicodeKeyName.Buffer, unicodeKeyName.MaximumLength);
+ DeviceInstanceRegistryPath->Buffer = buffer;
+ DeviceInstanceRegistryPath->Length = unicodeKeyName.Length;
+ DeviceInstanceRegistryPath->MaximumLength = unicodeKeyName.MaximumLength;
+ }
+ }
+
+PrepareForReturn:
+
+ ExFreePool(keyValueInformation);
+ return status;
+}
+#if DBG
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This routine displays debugging message or causes a break.
+
+Arguments:
+
+ Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
+ DEBUG_BREAK - displays message and break.
+
+ DebugMessage - supplies a pointer to the debugging message.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ if (Level == DEBUG_BREAK) {
+ DbgBreakPoint();
+ }
+
+ va_end(ap);
+}
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR c = ' ';
+
+ if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
+ c = 'A';
+ } else if (Desc->Option == IO_RESOURCE_PREFERRED) {
+ c = 'P';
+ }
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
+ Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
+ Desc->u.Port.Alignment,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
+ Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
+ Desc->u.Memory.Alignment,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Interrupt.MinimumVector,
+ Desc->u.Interrupt.MaximumVector
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Dma.MinimumChannel,
+ Desc->u.Dma.MaximumChannel
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays Io resource requirements list.
+
+Arguments:
+
+ IoList - supplies a pointer to the Io resource requirements list to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIO_RESOURCE_LIST resList;
+ PIO_RESOURCE_DESCRIPTOR resDesc;
+ ULONG listCount, count, i, j;
+
+ if (IoList == NULL) {
+ return;
+ }
+ DbgPrint("Pnp Bios IO Resource Requirements List for Slot %x -\n", IoList->SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", IoList->AlternativeLists, IoList->BusNumber);
+ listCount = IoList->AlternativeLists;
+ resList = &IoList->List[0];
+ for (i = 0; i < listCount; i++) {
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", resList->Version,
+ resList->Revision, resList->Count);
+ resDesc = &resList->Descriptors[0];
+ count = resList->Count;
+ for (j = 0; j < count; j++) {
+ PipDumpIoResourceDescriptor(" ", resDesc);
+ resDesc++;
+ }
+ resList = (PIO_RESOURCE_LIST) resDesc;
+ }
+}
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT Level: %x, Vector: %x, Affinity: %x\n",
+ Indent,
+ Desc->u.Interrupt.Level,
+ Desc->u.Interrupt.Vector,
+ Desc->u.Interrupt.Affinity
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA Channel: %x, Port: %x\n",
+ Indent,
+ Desc->u.Dma.Channel,
+ Desc->u.Dma.Port
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays CM resource list.
+
+Arguments:
+
+ CmList - supplies a pointer to CM resource list
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG count, i;
+
+ if (CmList) {
+ fullDesc = &CmList->List[0];
+ DbgPrint("Pnp Bios Cm Resource List -\n");
+ DbgPrint(" List Count = %x, Bus Number = %x\n", CmList->Count, fullDesc->BusNumber);
+ partialDesc = &fullDesc->PartialResourceList;
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", partialDesc->Version,
+ partialDesc->Revision, partialDesc->Count);
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ PipDumpCmResourceDescriptor(" ", desc);
+ desc++;
+ }
+ }
+}
+#endif
diff --git a/private/ntos/nthals/extender/pnpisa.sur/pbios.h b/private/ntos/nthals/extender/pnpisa.sur/pbios.h
new file mode 100644
index 000000000..6c1b2e333
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/pbios.h
@@ -0,0 +1,241 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbiosp.h
+
+Abstract:
+
+ PnP BIOS/ISA configuration data definitions
+
+Author:
+
+ Shie-Lin Tzong (shielint) April 12, 1995
+
+Revision History:
+
+--*/
+
+//#include "nthal.h"
+//#include "hal.h"
+
+//
+// Constants
+//
+
+#define SMALL_RESOURCE_TAG (UCHAR)(0x00)
+#define LARGE_RESOURCE_TAG (UCHAR)(0x80)
+#define SMALL_TAG_MASK 0xf8
+#define SMALL_TAG_SIZE_MASK 7
+
+//
+// Small Resouce Tags with length bits stripped off
+//
+
+#define TAG_VERSION 0x08
+#define TAG_LOGICAL_ID 0x10
+#define TAG_COMPATIBLE_ID 0x18
+#define TAG_IRQ 0x20
+#define TAG_DMA 0x28
+#define TAG_START_DEPEND 0x30
+#define TAG_END_DEPEND 0x38
+#define TAG_IO 0x40
+#define TAG_IO_FIXED 0x48
+#define TAG_VENDOR 0x70
+#define TAG_END 0x78
+
+//
+// Large Resouce Tags
+//
+
+#define TAG_MEMORY 0x81
+#define TAG_ANSI_ID 0x82
+#define TAG_UNICODE_ID 0x83
+#define TAG_LVENDOR 0x84
+#define TAG_MEMORY32 0x85
+#define TAG_MEMORY32_FIXED 0x86
+
+//
+// Complete TAG if applicable.
+//
+
+#define TAG_COMPLETE_COMPATIBLE_ID 0x1C
+#define TAG_COMPLETE_END 0x79
+
+#include "pshpack1.h"
+
+//
+// PNP ISA Port descriptor definition
+//
+
+typedef struct _PNP_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01000111B, small item name = 08, length = 7
+ UCHAR Information; // bit [0] = 1 device decodes full 16 bit addr
+ // = 0 device decodes ISA addr bits[9-0]
+ USHORT MinimumAddress;
+ USHORT MaximumAddress;
+ UCHAR Alignment; // Increment in 1 byte blocks
+ UCHAR Length; // # contiguous Port requested
+} PNP_PORT_DESCRIPTOR, *PPNP_PORT_DESCRIPTOR;
+
+//
+// PNP ISA fixed Port descriptor definition
+//
+
+typedef struct _PNP_FIXED_PORT_DESCRIPTOR_ {
+ UCHAR Tag; // 01001011B, small item name = 09, length = 3
+ USHORT MinimumAddress;
+ UCHAR Length; // # contiguous Port requested
+} PNP_FIXED_PORT_DESCRIPTOR, *PPNP_FIXED_PORT_DESCRIPTOR;
+
+//
+// PNP ISA IRQ descriptor definition
+//
+
+typedef struct _PNP_IRQ_DESCRIPTOR_ {
+ UCHAR Tag; // 0010001XB small item name = 4 length = 2/3
+ USHORT IrqMask; // bit 0 is irq 0
+ UCHAR Information; // Optional
+} PNP_IRQ_DESCRIPTOR, *PPNP_IRQ_DESCRIPTOR;
+
+//
+// Masks for PNP_IRQ_DESCRIPTOR Information byte
+//
+
+#define PNP_IRQ_LEVEL_MASK 0xC
+#define PNP_IRQ_EDGE_MASK 0x3
+
+//
+// PNP ISA DMA descriptor definition
+//
+
+typedef struct _PNP_DMA_DESCRIPTOR_ {
+ UCHAR Tag; // 00101010B, small item name = 05, length = 2
+ UCHAR ChannelMask; // bit 0 is channel 0
+ UCHAR Flags; // see spec
+} PNP_DMA_DESCRIPTOR, *PPNP_DMA_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY descriptor
+//
+
+typedef struct _PNP_MEMORY_DESCRIPTOR_ {
+ UCHAR Tag; // 10000001B, Large item name = 1
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ USHORT MinimumAddress; // address bit [8-23]
+ USHORT MaximumAddress; // address bit [8-23]
+ USHORT Alignment; // 0x0000 = 64KB
+ USHORT MemorySize; // In 256 byte blocks
+} PNP_MEMORY_DESCRIPTOR, *PPNP_MEMORY_DESCRIPTOR;
+
+//
+// PNP ISA MEMORY32 descriptor
+//
+
+typedef struct _PNP_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000101B, Large item name = 5
+ USHORT Length; // Length of the descriptor = 17
+ UCHAR Information; // See def below
+ ULONG MinimumAddress; // 32 bit addr
+ ULONG MaximumAddress; // 32 bit addr
+ ULONG Alignment; // 32 bit alignment
+ ULONG MemorySize; // 32 bit length
+} PNP_MEMORY32_DESCRIPTOR, *PPNP_MEMORY32_DESCRIPTOR;
+
+//
+// PNP ISA FIXED MEMORY32 descriptor
+//
+
+typedef struct _PNP_FIXED_MEMORY32_DESCRIPTOR_ {
+ UCHAR Tag; // 10000110B, Large item name = 6
+ USHORT Length; // Length of the descriptor = 9
+ UCHAR Information; // See def below
+ ULONG BaseAddress; // 32 bit addr
+ ULONG MemorySize; // 32 bit length
+} PNP_FIXED_MEMORY32_DESCRIPTOR, *PPNP_FIXED_MEMORY32_DESCRIPTOR;
+
+#define PNP_MEMORY_ROM_MASK 0x40
+#define PNP_MEMORY_SHADOWABLE_MASK 0x20
+#define PNP_MEMORY_CONTROL_MASK 0x18
+ #define PNP_MEMORY_CONTROL_8BIT 00
+ #define PNP_MEMORY_CONTROL_16BIT 01
+ #define PNP_MEMORY_CONTROL_8AND16BIT 02
+ #define PNP_MEMORY_CONTROL_32BIT 03
+#define PNP_MEMORY_SUPPORT_TYPE_MASK 04
+#define PNP_MEMORY_CACHE_SUPPORT_MASK 02
+#define PNP_MEMORY_WRITE_STATUS_MASK 01
+
+#define UNKNOWN_DOCKING_IDENTIFIER 0xffffffff
+#define UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89
+#define FUNCTION_NOT_SUPPORTED 0x82
+#define SYSTEM_NOT_DOCKED 0x87
+
+//
+// Pnp BIOS device node structure
+//
+
+typedef struct _PNP_BIOS_DEVICE_NODE {
+ USHORT Size;
+ UCHAR Node;
+ ULONG ProductId;
+ UCHAR DeviceType[3];
+ USHORT DeviceAttributes;
+ // followed by AllocatedResourceBlock, PossibleResourceBlock
+ // and CompatibleDeviceId
+} PNP_BIOS_DEVICE_NODE, *PPNP_BIOS_DEVICE_NODE;
+
+//
+// DeviceType definition
+//
+
+#define BASE_TYPE_DOCKING_STATION 0xA
+
+//
+// Device attributes definitions
+//
+
+#define DEVICE_DOCKING 0x20
+#define DEVICE_REMOVABLE 0x40
+
+//
+// Pnp BIOS Installation check
+//
+
+typedef struct _PNP_BIOS_INSTALLATION_CHECK {
+ UCHAR Signature[4]; // $PnP (ascii)
+ UCHAR Revision;
+ UCHAR Length;
+ USHORT ControlField;
+ UCHAR Checksum;
+ ULONG EventFlagAddress; // Physical address
+ USHORT RealModeEntryOffset;
+ USHORT RealModeEntrySegment;
+ USHORT ProtectedModeEntryOffset;
+ ULONG ProtectedModeCodeBaseAddress;
+ ULONG OemDeviceId;
+ USHORT RealModeDataBaseAddress;
+ ULONG ProtectedModeDataBaseAddress;
+} PNP_BIOS_INSTALLATION_CHECK, *PPNP_BIOS_INSTALLATION_CHECK;
+
+#include "poppack.h"
+
+//
+// Pnp BIOS ControlField masks
+//
+
+#define PNP_BIOS_CONTROL_MASK 0x3
+#define PNP_BIOS_EVENT_NOT_SUPPORTED 0
+#define PNP_BIOS_EVENT_POLLING 1
+#define PNP_BIOS_EVENT_ASYNC 2
+
+//
+// Pnp Bios event
+//
+
+#define ABOUT_TO_CHANGE_CONFIG 1
+#define DOCK_CHANGED 2
+#define SYSTEM_DEVICE_CHANGED 3
+#define CONFIG_CHANGE_FAILED 4
diff --git a/private/ntos/nthals/extender/pnpisa.sur/pnpisa.h b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.h
new file mode 100644
index 000000000..15b12eeda
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.h
@@ -0,0 +1,164 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pnpisa.h
+
+Abstract:
+
+ This module contins definitions/declarations for PNP ISA related
+ definitions.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-12-1995
+
+Revision History:
+
+--*/
+
+//
+// External references
+//
+
+extern PUCHAR PipReadDataPort;
+extern PUCHAR PipAddressPort;
+extern PUCHAR PipCommandPort;
+
+//
+// Definitions
+//
+
+#ifndef NEC_98
+
+#define ADDRESS_PORT 0x0279
+#define COMMAND_PORT 0x0a79
+
+#else
+
+#define ADDRESS_PORT 0x0259
+#define COMMAND_PORT 0x0a59
+
+#endif // NEC_98
+
+//
+// Plug and Play Card Control Registers
+//
+
+#define SET_READ_DATA_PORT 0x00
+#define SERIAL_ISOLATION_PORT 0x01
+#define CONFIG_CONTROL_PORT 0x02
+#define WAKE_CSN_PORT 0x03
+#define CONFIG_DATA_PORT 0x04
+#define CONFIG_DATA_STATUS_PORT 0x05
+#define SET_CSN_PORT 0x06
+#define LOGICAL_DEVICE_PORT 0x07
+
+//
+// Plug and Play Logical Device Control Registers
+//
+
+#define ACTIVATE_PORT 0x30
+#define IO_RANGE_CHECK_PORT 0x31
+
+//
+// Config Control command
+//
+
+#define CONTROL_WAIT_FOR_KEY 0x02
+#define CONTROL_RESET_CSN 0x04
+
+//
+// Memory Space Configuration
+//
+
+#define NUMBER_MEMORY_DESCRIPTORS 4
+#define ADDRESS_MEMORY_BASE 0x40
+#define ADDRESS_MEMORY_INCR 0x08
+#define ADDRESS_MEMORY_HI 0x00
+#define ADDRESS_MEMORY_LO 0x01
+#define ADDRESS_MEMORY_CTL 0x02
+#define ADDRESS_MEMORY_CTL_LIMIT 0x01
+#define ADDRESS_MEMORY_UPPER_HI 0x03
+#define ADDRESS_MEMORY_UPPER_LO 0x04
+
+//
+// 32 Bit Memory Space Configuration
+//
+
+#define NUMBER_32_MEMORY_DESCRIPTORS 4
+#define ADDRESS_32_MEMORY_BASE(x) ((PUCHAR)(0x70+((x)*0x10)+((x==0) ? 6 : 0)))
+#define ADDRESS_32_MEMORY_B3 0x0
+#define ADDRESS_32_MEMORY_B2 0x1
+#define ADDRESS_32_MEMORY_B1 0x2
+#define ADDRESS_32_MEMORY_B0 0x3
+#define ADDRESS_32_MEMORY_CTL 0x4
+#define ADDRESS_32_MEMORY_E3 0x5
+#define ADDRESS_32_MEMORY_E2 0x6
+#define ADDRESS_32_MEMORY_E1 0x7
+#define ADDRESS_32_MEMORY_E0 0x8
+
+//
+// Io Space Configuration
+//
+
+#define NUMBER_IO_DESCRIPTORS 8
+#define ADDRESS_IO_BASE 0x60
+#define ADDRESS_IO_INCR 0x02
+#define ADDRESS_IO_BASE_HI 0x00
+#define ADDRESS_IO_BASE_LO 0x01
+
+//
+// Interrupt Configuration
+//
+
+#define NUMBER_IRQ_DESCRIPTORS 2
+#define ADDRESS_IRQ_BASE 0x70
+#define ADDRESS_IRQ_INCR 0x02
+#define ADDRESS_IRQ_VALUE 0x00
+#define ADDRESS_IRQ_TYPE 0x01
+
+//
+// DMA Configuration
+//
+
+#define NUMBER_DMA_DESCRIPTORS 2
+#define ADDRESS_DMA_BASE 0x74
+#define ADDRESS_DMA_INCR 0x01
+#define ADDRESS_DMA_VALUE 0x00
+#define NO_DMA 0x04
+
+//
+// 9 byte serial identifier of a PNP ISA Card
+//
+
+#include "pshpack1.h"
+typedef struct _SERIAL_IDENTIFIER_ {
+ ULONG VenderId;
+ ULONG SerialNumber;
+ UCHAR Checksum;
+} SERIAL_IDENTIFIER, *PSERIAL_IDENTIFIER;
+#include "poppack.h"
+
+//
+// Misc. definitions
+//
+
+#define MIN_READ_DATA_PORT 0x200
+#define MAX_READ_DATA_PORT 0x3ff
+#define MAX_CHARACTER_LENGTH 255
+#define NUMBER_CARD_ID_BYTES 9
+#define NUMBER_CARD_ID_BITS (NUMBER_CARD_ID_BYTES * 8)
+#define CHECKSUMED_BITS 64
+#define LFSR_SEED 0x6A
+#define ISOLATION_TEST_BYTE_1 0x55
+#define ISOLATION_TEST_BYTE_2 0xAA
+
+#define PipWriteAddress(data) WRITE_PORT_UCHAR (PipAddressPort, (UCHAR)(data))
+#define PipWriteData(data) WRITE_PORT_UCHAR (PipCommandPort, (UCHAR)(data))
+#define PipReadData() READ_PORT_UCHAR (PipReadDataPort)
+
+
+
diff --git a/private/ntos/nthals/extender/pnpisa.sur/pnpisa.rc b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.rc
new file mode 100644
index 000000000..4422bbfd2
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/pnpisa.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 "PNP ISA Driver"
+#define VER_INTERNALNAME_STR "pnpisa.sys"
+#define VER_ORIGINALFILENAME_STR "pnpisa.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pnpisa.sur/resource.c b/private/ntos/nthals/extender/pnpisa.sur/resource.c
new file mode 100644
index 000000000..4e81668a5
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/resource.c
@@ -0,0 +1,680 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ This module contains the high level device resources support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-27-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "pbios.h"
+
+#define IDBG 0
+
+#pragma alloc_text(INIT,PipGetCardIdentifier)
+#pragma alloc_text(INIT,PipGetFunctionIdentifier)
+#pragma alloc_text(INIT,PipGetCompatibleDeviceId)
+#pragma alloc_text(INIT,PipQueryDeviceId)
+#pragma alloc_text(INIT,PipQueryDeviceUniqueId)
+#pragma alloc_text(INIT,PipQueryDeviceResources)
+#pragma alloc_text(INIT,PipQueryDeviceResourceRequirements)
+#pragma alloc_text(INIT,PipSetDeviceResources)
+
+NTSTATUS
+PipGetCardIdentifier (
+ PUCHAR CardData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ This function returns the identifier for a pnpisa card.
+
+Arguments:
+
+ CardData - supplies a pointer to the pnp isa device data.
+
+ Buffer - supplies a pointer to variable to receive a pointer to the Id.
+
+ BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ UCHAR tag;
+ LONG size, length;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ PCHAR ansiBuffer;
+
+ *Buffer = NULL;
+ *BufferLength = 0;
+
+ tag = *CardData;
+
+ //
+ // Make sure CardData does *NOT* point to a Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ DbgPrint("PipGetCardIdentifier: CardData is at a Logical Id tag\n");
+ return status;
+ }
+
+ //
+ // Find the resource descriptor which describle identifier string
+ //
+
+ do {
+
+ //
+ // Do we find the identifer resource tag?
+ //
+
+ if (tag == TAG_ANSI_ID) {
+ CardData++;
+ length = *(PUSHORT)CardData;
+ CardData += 2;
+ ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
+ if (ansiBuffer == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ RtlMoveMemory(ansiBuffer, CardData, length);
+ ansiBuffer[length] = 0;
+ RtlInitAnsiString(&ansiString, ansiBuffer);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ ExFreePool(ansiBuffer);
+ *Buffer = unicodeString.Buffer;
+ *BufferLength = unicodeString.Length + sizeof(WCHAR);
+ break;
+ }
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(CardData + 1);
+ size += 3; // length of large tag
+ }
+
+ CardData += size;
+ tag = *CardData;
+
+ } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
+
+ return status;
+}
+
+NTSTATUS
+PipGetFunctionIdentifier (
+ PUCHAR DeviceData,
+ PWCHAR *Buffer,
+ PULONG BufferLength
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp isa identifier for the specified
+ DeviceData/LogicalFunction. The Identifier for a logical function is
+ optional. If no Identifier available , Buffer is set to NULL.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the pnp isa device data.
+
+ Buffer - supplies a pointer to variable to receive a pointer to the Id.
+
+ BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ UCHAR tag;
+ LONG size, length;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ PCHAR ansiBuffer;
+
+ *Buffer = NULL;
+ *BufferLength = 0;
+
+ tag = *DeviceData;
+
+#if DBG
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ DbgPrint("PipGetFunctionIdentifier: DeviceData is not at a Logical Id tag\n");
+ }
+#endif
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ do {
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(DeviceData + 1);
+ size += 3; // length of large tag
+ }
+
+ DeviceData += size;
+ tag = *DeviceData;
+
+ //
+ // Do we find the identifer resource tag?
+ //
+
+ if (tag == TAG_ANSI_ID) {
+ DeviceData++;
+ length = *(PUSHORT)DeviceData;
+ DeviceData += 2;
+ ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
+ if (ansiBuffer == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ RtlMoveMemory(ansiBuffer, DeviceData, length);
+ ansiBuffer[length] = 0;
+ RtlInitAnsiString(&ansiString, ansiBuffer);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ ExFreePool(ansiBuffer);
+ *Buffer = unicodeString.Buffer;
+ *BufferLength = unicodeString.Length + sizeof(WCHAR);
+ break;
+ }
+
+ } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
+
+ return status;
+}
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR *Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp isa id for the specified DeviceData
+ and Id index. If Id index = 0, the Hardware ID will be return; if id
+ index = n, the Nth compatible id will be returned.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the pnp isa device data.
+
+ IdIndex - supplies the index of the compatible id desired.
+
+ Buffer - supplies a pointer to variable to receive a pointer to the compatible Id.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_NO_MORE_ENTRIES;
+ UCHAR tag;
+ ULONG count = 0;
+ LONG size;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ ULONG id;
+
+ tag = *DeviceData;
+
+#if DBG
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
+ }
+#endif
+
+ if (IdIndex == 0) {
+
+ //
+ // Caller is asking for hardware id
+ //
+
+ DeviceData++; // Skip tag
+ id = *(PULONG)DeviceData;
+ status = STATUS_SUCCESS;
+ } else {
+
+ //
+ // caller is asking for compatible id
+ //
+
+ IdIndex--;
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ do {
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(DeviceData + 1);
+ size += 3; // length of large tag
+ }
+
+ DeviceData += size;
+ tag = *DeviceData;
+
+ //
+ // Do we reach the compatible ID descriptor?
+ //
+
+ if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) {
+ if (count == IdIndex) {
+ id = *(PULONG)(DeviceData + 1);
+ status = STATUS_SUCCESS;
+ break;
+ } else {
+ count++;
+ }
+ }
+
+ } while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
+ }
+
+ if (NT_SUCCESS(status)) {
+ PipDecompressEisaId(id, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ *Buffer = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ sizeof(L"*") + sizeof(WCHAR) + unicodeString.Length
+ );
+ if (*Buffer) {
+ swprintf(*Buffer, L"*%s", unicodeString.Buffer);
+ } else {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlFreeUnicodeString(&unicodeString);
+ }
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId
+ )
+/*++
+
+Routine Description:
+
+ This function returns the unique id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ DeviceId - supplies a pointer to a variable to receive device id.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // Set up device's unique id.
+ // device unique id = SerialNumber of the card
+ //
+
+ *DeviceId = (PWCHAR)ExAllocatePool (
+ PagedPool,
+ (8 + 1) * sizeof(WCHAR) // serial number + null
+ );
+ if (*DeviceId) {
+ swprintf (*DeviceId,
+ L"%08X",
+ ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber
+ );
+#if IDBG
+ {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, *DeviceId);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("PnpIsa: return Unique Id = %s\n", ansiString.Buffer);
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+ } else {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+
+ }
+
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PWCHAR *DeviceId,
+ ULONG IdIndex
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular device.
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied device.
+
+ DeviceId - supplies a pointer to a variable to receive the device id.
+
+ IdIndex - specifies device id or compatible id (0 - device id)
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWSTR format;
+ ULONG size;
+ UCHAR eisaId[8];
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+
+ //
+ // Set up device's id.
+ // device id = VenderId + Logical device number
+ //
+
+ if (DeviceInfo->CardInformation->NumberLogicalDevices == 1) {
+ format = L"ISAPNP\\%s";
+ size = sizeof(L"ISAPNP\\*") + sizeof(WCHAR);
+ } else {
+ format = L"ISAPNP\\%s_DEV%04X";
+ size = sizeof(L"ISAPNP\\_DEV") + 4 * sizeof(WCHAR) + sizeof(WCHAR);
+ }
+ PipDecompressEisaId(
+ ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->VenderId,
+ eisaId
+ );
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ size += unicodeString.Length;
+ *DeviceId = (PWCHAR)ExAllocatePool (PagedPool, size);
+ if (*DeviceId) {
+ swprintf (*DeviceId,
+ format,
+ unicodeString.Buffer,
+ DeviceInfo->LogicalDeviceNumber
+ );
+#if IDBG
+ {
+ ANSI_STRING dbgAnsiString;
+ UNICODE_STRING dbgUnicodeString;
+
+ RtlInitUnicodeString(&dbgUnicodeString, *DeviceId);
+ RtlUnicodeStringToAnsiString(&dbgAnsiString, &dbgUnicodeString, TRUE);
+ DbgPrint("PnpIsa: return device Id = %s\n", dbgAnsiString.Buffer);
+ RtlFreeAnsiString(&dbgAnsiString);
+ }
+#endif
+ } else {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlFreeUnicodeString(&unicodeString);
+
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ PCM_RESOURCE_LIST *CmResources,
+ ULONG *Size
+ )
+/*++
+
+Routine Description:
+
+ This function returns the bus resources being used by the specified device
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied slot
+
+ BusNumber - should always be 0
+
+ CmResources - supplies a pointer to a variable to receive the device resource
+ data.
+
+ Size - Supplies a pointer to avariable to receive the size of device resource
+ data.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ ULONG length;
+ NTSTATUS status;
+ PCM_RESOURCE_LIST cmResources;
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber,
+ FALSE
+ );
+
+ status = PipReadDeviceBootResourceData (
+ BusNumber,
+ DeviceInfo->DeviceData,
+ &cmResources,
+ &length
+ );
+
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+ cmResources = NULL; // Just to make sure.
+ }
+ *CmResources = cmResources;
+ *Size = length;
+#if IDBG
+ PipDumpCmResourceList(cmResources);
+#endif
+ }
+ return status;
+}
+
+NTSTATUS
+PipQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ ULONG BusNumber,
+ ULONG Slot,
+ PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
+ ULONG *Size
+ )
+/*++
+
+Routine Description:
+
+ This function returns the possible bus resources that this device may be
+ satisfied with.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied slot
+
+ BusNumber - Supplies the bus number
+
+ Slot - supplies the slot number of the BusNumber
+
+ IoResources - supplies a pointer to a variable to receive the IO resource
+ requirements list
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length = 0;
+ NTSTATUS status;
+ PUCHAR deviceData;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
+
+ deviceData = DeviceInfo->DeviceData;
+ status = PbBiosResourcesToNtResources (
+ BusNumber,
+ Slot,
+ &deviceData,
+ &ioResources,
+ &length
+ );
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+ ioResources = NULL; // Just ot make sure
+ }
+ *IoResources = ioResources;
+ *Size = length;
+#if IDBG
+ PipDumpIoResourceList(ioResources);
+#endif
+ }
+ return status;
+}
+
+NTSTATUS
+PipSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PCM_RESOURCE_LIST CmResources
+ )
+/*++
+
+Routine Description:
+
+ This function configures the device to the specified device setttings
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied slot
+
+ CmResources - pointer to the desired resource list
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+{
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber,
+ FALSE
+ );
+
+ //
+ // Set resource settings for the device
+ //
+
+ status = PipWriteDeviceBootResourceData (
+ DeviceInfo->DeviceData,
+ (PCM_RESOURCE_LIST) CmResources
+ );
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ return status;
+}
diff --git a/private/ntos/nthals/extender/pnpisa.sur/sources b/private/ntos/nthals/extender/pnpisa.sur/sources
new file mode 100644
index 000000000..f0b391be2
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa.sur/sources
@@ -0,0 +1,47 @@
+!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
+
+ALT_PROJECT_TARGET=dlibbin
+
+MAJORCOMP=ntos
+MINORCOMP=extender
+
+TARGETNAME=pnpisa
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=pnpisa.rc \
+ bus.c \
+ data.c \
+ init.c \
+ isolate.c \
+ misc.c \
+ convert.c \
+ resource.c
+
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=
diff --git a/private/ntos/nthals/extender/pnpisa/i386/bus.c b/private/ntos/nthals/extender/pnpisa/i386/bus.c
new file mode 100644
index 000000000..f4c6dd4df
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/bus.c
@@ -0,0 +1,1036 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ bus.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+
+PDEVICE_INFORMATION
+PipFindDeviceInformation (
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ );
+
+PCARD_INFORMATION
+PipFindCardInformation (
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN PSERIAL_IDENTIFIER Id
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PiQueryBusSlots)
+#pragma alloc_text(PAGE,PiReferenceDeviceHandler)
+#pragma alloc_text(PAGE,PipCheckBus)
+#endif
+
+
+ULONG
+PiGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Isa bus data for a device.
+ This API is not supported.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+PiSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ The function sets the Pnp Isa bus data for a device.
+ This API is not supported.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to be set.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+ return 0;
+}
+
+ULONG
+PiGetDeviceData (
+ 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
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pnp Isa device data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ ULONG dataLength;
+ PDEVICE_INFORMATION deviceInfo;
+
+ UNREFERENCED_PARAMETER ( DataType);
+
+ dataLength = 0;
+ deviceInfo = DeviceHandler2DeviceInfo (DeviceHandler);
+
+ //
+ // Synchronize with other pnp Isa service functions accessing device data.
+ //
+
+ ExAcquireFastMutex(&PipMutex);
+
+ //
+ // Verify caller has a valid DeviceHandler object
+ //
+
+ if (!(deviceInfo->Flags & DEVICE_FLAGS_VALID)) {
+
+ //
+ // Obsolete object, return no data
+ //
+
+ ExReleaseFastMutex(&PipMutex);
+ return dataLength;
+ }
+
+ //
+ // Get the device's data.
+ //
+
+ dataLength = deviceInfo->DeviceDataLength;
+ if (Offset < dataLength) {
+ dataLength -= Offset;
+ if (dataLength > Length) {
+ dataLength = Length;
+ }
+ RtlMoveMemory(Buffer, (PUCHAR)deviceInfo->DeviceData + Offset, dataLength);
+ } else {
+ dataLength = 0;
+ }
+
+ ExReleaseFastMutex(&PipMutex);
+ return dataLength;
+}
+
+ULONG
+PiSetDeviceData (
+ 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
+ )
+/*++
+
+Routine Description:
+
+ The function sets Pnp Isa device data for a device.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ DeviceHandler - supplies a pointer to a DEVICE_HANDLER_OBJECT
+
+ DataType - Specifies the type of device data desired.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the offset to the device data to start reading.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data set.
+
+--*/
+{
+ //
+ // We don't let drivers change Pnp device data.
+ //
+
+ return 0;
+}
+
+NTSTATUS
+PiQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ The function returns a list of currently available SlotNumber.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the handler of the bus.
+
+ RootHandler - supplies a pointer to a BUS_HANDLER for the originating
+ request.
+
+ Buffer - Supplies the space to store the data.
+
+ SlotNumber - Supplies a variable to receives the number of available slots.
+
+ Length - Supplies a count in bytes of the stored data. If this function
+ returns STATUS_BUFFER_TOO_SMALL, this variable supplies the required
+ size.
+
+Return Value:
+
+ STATUS_BUFFER_TOO_SMALL if caller supplied buffer is not big enough.
+
+--*/
+
+{
+ PPI_BUS_EXTENSION busExtension;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_INFORMATION deviceInfo;
+ ULONG count = 0;
+
+ PAGED_CODE ();
+
+ busExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+
+ //
+ // Synchronize with other pnp Isa device handle assignment.
+ //
+
+ ExAcquireFastMutex(&PipMutex);
+
+ //
+ // Fill in returned buffer length, or what size buffer is needed
+ //
+
+ *ReturnedLength = busExtension->NoValidSlots * sizeof (ULONG);
+ if (BufferSize < *ReturnedLength) {
+
+ //
+ // Callers buffer is not large enough
+ //
+
+ ExReleaseFastMutex (&PipMutex);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Return caller all the possible slot number
+ //
+
+ for (link = busExtension->DeviceList.Next; link; link = link->Next) {
+ deviceInfo = CONTAINING_RECORD (link, DEVICE_INFORMATION, DeviceList);
+ if (deviceInfo->Flags & DEVICE_FLAGS_VALID) {
+ *SlotNumbers = DeviceInfoSlot(deviceInfo);
+ SlotNumbers++;
+ count += 1;
+ }
+ }
+
+ *ReturnedLength = count * sizeof (ULONG);
+ ExReleaseFastMutex (&PipMutex);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PiDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ The function is the bus handler specific verion of HalDeviceControl.
+
+Arguments:
+
+ Context - The DeviceControl context. The context has all the information
+ for the HalDeviceControl operation being performed.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ ULONG i, junk;
+ ULONG controlCode;
+ PULONG bufferLength;
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+
+ for (i = 0; i < NUMBER_DEVICE_CONTROL_FUNCTIONS; i++) {
+
+ if (PipDeviceControl[i].ControlCode == Context->DeviceControl.ControlCode) {
+ if (PipDeviceControl[i].ControlHandler == NULL) {
+ status = Context->DeviceControl.Status = STATUS_NOT_IMPLEMENTED;
+ goto deviceControlDone;
+ }
+
+ //
+ // Found DeviceControl handler and save it to HAL_DEVICE_CONTROL_CONTEXT
+ // structure.
+ //
+
+ Context->ContextControlHandler = (ULONG)(PipDeviceControl + i);
+
+ //
+ // Verify callers buffer is the min required length
+ //
+
+ if (*Context->DeviceControl.BufferLength < PipDeviceControl[i].MinBuffer) {
+ Context->DeviceControl.Status = STATUS_BUFFER_TOO_SMALL;
+ *Context->DeviceControl.BufferLength = PipDeviceControl[i].MinBuffer;
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto deviceControlDone;
+ }
+
+ if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
+
+ //
+ // All supported slot control functions touch paged code or data.
+ // If the current irql is low enough go dispatch now; otherwise,
+ // queue the request to a worker thread.
+ //
+
+ PipDispatchControl (Context);
+
+ } else {
+
+ //
+ // Enqueue to worker thread
+ //
+
+ ExInterlockedInsertTailList (
+ &PipControlWorkerList,
+ (PLIST_ENTRY) &Context->ContextWorkQueue,
+ &PipSpinlock
+ );
+
+ //
+ // Make sure worker is requested
+ //
+
+ PipStartWorker ();
+ }
+ return STATUS_PENDING;
+ }
+ }
+
+deviceControlDone:
+ HalCompleteDeviceControl (Context);
+ return status;
+}
+
+PDEVICE_HANDLER_OBJECT
+PiReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function returns a reference to the devce handler specified by SlotNumber
+ and BusHandler.
+
+Arguments:
+
+ BusHandler - Supplies a pointer to the bus handler structure for the bus
+
+ RootHanler - Supplies a pointer to the root bus handler structure for the bus
+
+ SlotNumber - Specifies the SlotNumber of the device to be referenced
+
+Return Value:
+
+ a reference to DEVICE_HANDLER_OBJECT.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PPI_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+
+ PAGED_CODE ();
+
+ ExAcquireFastMutex (&PipMutex);
+
+ busExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+ deviceInfo = PipFindDeviceInformation (busExtension, SlotNumber);
+ deviceHandler = NULL;
+ if (deviceInfo) {
+ deviceHandler = DeviceInfo2DeviceHandler (deviceInfo);
+ status = ObReferenceObjectByPointer(
+ deviceHandler,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoDeviceHandlerObjectType,
+ KernelMode
+ );
+
+ if (!NT_SUCCESS(status)) {
+ deviceHandler = NULL;
+ }
+ }
+
+ ExReleaseFastMutex (&PipMutex);
+ return deviceHandler;
+}
+
+PDEVICE_INFORMATION
+PipFindDeviceInformation (
+ IN PPI_BUS_EXTENSION BusExtension,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ The function goes through device data list to find the desired SlotNumber's
+ device data. The caller must hold the PipMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to current bus'es extension.
+
+ SlotNumber - specified the desired device data.
+
+Return Value:
+
+ A pointer to the DEVICE_INFORMATION if found. Otherwise a value of NULL is returned.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PSINGLE_LIST_ENTRY link;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ //
+ // Go through the slot data link list to find a match.
+ //
+
+ for (link = BusExtension->DeviceList.Next; link; link = link->Next) {
+ deviceInfo = CONTAINING_RECORD (link, DEVICE_INFORMATION, DeviceList);
+ if (DeviceInfoSlot(deviceInfo) == SlotNumber) {
+ break;
+ }
+ }
+
+ if (!link) {
+ return NULL;
+ } else {
+ return deviceInfo;
+ }
+}
+
+VOID
+PipCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+
+/*++
+
+Routine Description:
+
+ The function enumerates the bus specified by BusHandler.
+ BUGBUG, Currently the bus extender will not unload even if all the pnp isa
+ cards are gone.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the BusHandler of the bus to be enumerated.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PPI_BUS_EXTENSION busExtension;
+ NTSTATUS status;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ ULONG objectSize, noDevices;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ PUCHAR cardData;
+ ULONG dataLength;
+ USHORT csn, i;
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ UCHAR tmp;
+ BOOLEAN notifyBusCheck;
+ PSINGLE_LIST_ENTRY link;
+
+ PAGED_CODE();
+
+ busExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+ notifyBusCheck = FALSE;
+
+ //
+ // We may be removing references to this bus handler, so add
+ // a reference now.
+ //
+
+ HalReferenceBusHandler (BusHandler);
+
+ //
+ // Acquire fast mutex to access device data
+ //
+
+ ExAcquireFastMutex (&PipMutex);
+ PipInvalidateCards(busExtension);
+
+ //
+ // Perform Pnp isolation process. This will assign card select number for each
+ // Pnp Isa card isolated by the system. All the isolated cards will be put into
+ // wait-for-key state.
+ //
+
+ ExAcquireFastMutex(&PipPortMutex);
+
+ PipIsolateCards(&busExtension->NumberCSNs, &busExtension->ReadDataPort);
+ PipLFSRInitiation (); // send initiation key to put cards into sleep state
+
+ //
+ // For each card selected build CardInformation and DeviceInformation structures.
+ //
+
+ for (csn = 1; csn <= busExtension->NumberCSNs; csn++) {
+
+ status = PipReadCardResourceData (
+ csn,
+ &noDevices,
+ &cardData,
+ &dataLength);
+ if (!NT_SUCCESS(status)) {
+ continue;
+ }
+ cardInfo = PipFindCardInformation(busExtension, (PSERIAL_IDENTIFIER)cardData);
+ if (cardInfo) {
+
+ //
+ // Find an existing card information structure with the same serial identifier
+ // Go validate the card information and its associated device information.
+ //
+
+ cardInfo->Flags |= CARD_FLAGS_VALID;
+ cardInfo->CardSelectNumber = csn;
+ for (link = cardInfo->LogicalDeviceList.Next; link; link = link->Next) {
+ deviceInfo = CONTAINING_RECORD (link, DEVICE_INFORMATION, LogicalDeviceList);
+ deviceInfo->Flags |= DEVICE_FLAGS_VALID;
+ }
+ ExFreePool(cardData);
+ } else {
+
+ //
+ // Did not find an existing card information matched the card data.
+ // Allocate and initialize new card information and its associate device
+ // information structures.
+ //
+
+ cardInfo = (PCARD_INFORMATION)ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof(CARD_INFORMATION),
+ 'iPnP');
+ if (!cardInfo) {
+ ExFreePool(cardData);
+#if DBG
+ DebugPrint((DEBUG_MESSAGE, "PnpIsa:failed to allocate CARD_INFO structure\n"));
+#endif
+ continue;
+ }
+
+ //
+ // Initialize card information structure
+ //
+
+ RtlZeroMemory(cardInfo, sizeof(CARD_INFORMATION));
+ cardInfo->Flags = CARD_FLAGS_VALID;
+ cardInfo->CardSelectNumber = csn;
+ cardInfo->NumberLogicalDevices = noDevices;
+ cardInfo->CardData = cardData;
+ cardInfo->CardDataLength = dataLength;
+
+ ExInterlockedPushEntryList (
+ &busExtension->CardList,
+ &cardInfo->CardList,
+ &PipSpinlock
+ );
+#if DBG
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsa: adding one pnp card %x\n"));
+#endif
+ //
+ // For each logical device supported by the card build its DEVICE_INFORMATION
+ // structures and enable it.
+ //
+
+ cardData += sizeof(SERIAL_IDENTIFIER);
+ dataLength -= sizeof(SERIAL_IDENTIFIER);
+ PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+ for (i = 0; i < noDevices; i++) { // logical device number starts from 0
+
+ //
+ // Select the logical device, disable its io range check and
+ // enable the device.
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(i);
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+// PipWriteAddress(ACTIVATE_PORT);
+// PipWriteData(1);
+
+ notifyBusCheck = TRUE;
+
+ //
+ // Initialize the object attributes that will be used to create the
+ // Device Handler Object.
+ //
+
+ InitializeObjectAttributes(
+ &objectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+
+ objectSize = PipDeviceHandlerObjectSize + sizeof (DEVICE_INFORMATION);
+
+ //
+ // 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 = busExtension->NextSlotNumber++;
+
+ //
+ // 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)) {
+
+ //
+ // BUGBUG, Deallocate, free reference of the device handler?
+ //
+
+ //
+ // Object not created correctly. Skip this slot.
+ //
+
+ continue;
+ }
+
+ ZwClose (handle);
+
+ //
+ // Intialize device tracking structure
+ //
+
+ deviceHandler->BusHandler = BusHandler;
+ HalReferenceBusHandler(BusHandler);
+
+ deviceInfo = DeviceHandler2DeviceInfo(deviceHandler);
+ deviceInfo->Flags |= DEVICE_FLAGS_VALID;
+ deviceInfo->CardInformation = cardInfo;
+ deviceInfo->LogicalDeviceNumber = i;
+ deviceInfo->DeviceData = cardData;
+ deviceInfo->DeviceDataLength = PipFindNextLogicalDeviceTag(&cardData, &dataLength);
+
+ ExInterlockedPushEntryList (
+ &cardInfo->LogicalDeviceList,
+ &deviceInfo->LogicalDeviceList,
+ &PipSpinlock
+ );
+#if DBG
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsa: adding slot %x\n", DeviceInfoSlot(deviceInfo)));
+#endif
+
+ //
+ // Add it to the list of devices for this bus
+ //
+
+ busExtension->NoValidSlots += 1;
+ ExInterlockedPushEntryList (
+ &busExtension->DeviceList,
+ &deviceInfo->DeviceList,
+ &PipSpinlock
+ );
+
+ }
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ ExReleaseFastMutex(&PipPortMutex);
+
+ //
+ // Go through the slot data link list to delete all the removed slots.
+ //
+
+ noDevices = busExtension->NoValidSlots;
+ PipDeleteCards(busExtension);
+ if (noDevices != busExtension->NoValidSlots) {
+ notifyBusCheck = TRUE;
+ }
+ ExReleaseFastMutex (&PipMutex);
+
+ //
+ // Undo reference to bus handler from top of function
+ //
+
+ HalDereferenceBusHandler (BusHandler);
+
+ //
+ // Do we need to notify the system buscheck callback?
+ //
+
+ if (notifyBusCheck) {
+ HAL_BUS_INFORMATION busInfo;
+
+ busInfo.BusType = BusHandler->InterfaceType;
+ busInfo.ConfigurationType = BusHandler->ConfigurationType;
+ busInfo.BusNumber = BusHandler->BusNumber;
+ busInfo.Reserved = 0;
+ ExNotifyCallback (
+ PipHalCallbacks.BusCheck,
+ &busInfo,
+ (PVOID)BusHandler->BusNumber
+ );
+ }
+}
+
+VOID
+PipInvalidateCards (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+
+/*++
+
+Routine Description:
+
+ The function goes through Pnp Isa Card list and marks all the cards and
+ the devices associated with the cards as invalid.
+ The caller must acquire PipMutex to call this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_INFORMATION deviceInfo;
+ PSINGLE_LIST_ENTRY cardLink, deviceLink;
+
+ //
+ // Go through the card link list to mark ALL the devices as
+ // in transition state.
+ //
+
+ for (cardLink = BusExtension->CardList.Next; cardLink; cardLink = cardLink->Next) {
+ cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
+ cardInfo->Flags &= ~CARD_FLAGS_VALID;
+
+ //
+ // For each logical device of the card mark it as invalid
+ //
+
+ for (deviceLink = cardInfo->LogicalDeviceList.Next; deviceLink; deviceLink = deviceLink->Next) {
+ deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
+ deviceInfo->Flags &= ~DEVICE_FLAGS_VALID;
+ }
+ }
+
+ //
+ // Reset the CSN number.
+ //
+
+ BusExtension->NumberCSNs = 0;
+}
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION BusExtension
+ )
+/*++
+
+Routine Description:
+
+ The function goes through card list and deletes all the invalid
+ cards and their associated logical devices.
+ Note the PipMutex must be acquired before calling this routine.
+
+Arguments:
+
+ BusExtension - supplies a pointer to the extension data of desired bus.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PDEVICE_INFORMATION deviceInfo;
+ PCARD_INFORMATION cardInfo;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ PSINGLE_LIST_ENTRY *cardLink, *deviceLink ;
+
+ //
+ // Go through the card link list to free all the devices
+ // marked as invalid.
+ //
+
+ cardLink = &BusExtension->CardList.Next;
+ while (*cardLink) {
+ cardInfo = CONTAINING_RECORD (*cardLink, CARD_INFORMATION, CardList);
+ if (!(cardInfo->Flags & CARD_FLAGS_VALID)) {
+
+ //
+ // For each logical device of the card mark it as invalid
+ //
+
+ deviceLink = &cardInfo->LogicalDeviceList.Next;
+ while (*deviceLink) {
+ deviceInfo = CONTAINING_RECORD (*deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
+#if DBG
+ DebugPrint((DEBUG_MESSAGE, "Remove slot %x on PnpIsa bus\n", DeviceInfoSlot(deviceInfo)));
+#endif
+ deviceHandler = DeviceInfo2DeviceHandler(deviceInfo);
+ ObDereferenceObject (deviceHandler);
+ HalDereferenceBusHandler (BusExtension->BusHandler);
+ BusExtension->NoValidSlots--;
+ *deviceLink = (*deviceLink)->Next;
+ }
+
+ //
+ // In theory I can't deallocate the card data and card info structures. Because device
+ // info structure may still exist. The deallocation should be done after device info
+ // structure ref count is decremented to zero and deallocated. Here I am safe to do
+ // so because DispatchControl routine checks DeviceInfo flag to make sure it is valid
+ // before reference card data and card info.
+ //
+
+ if (cardInfo->CardData) {
+ ExFreePool(cardInfo->CardData);
+ }
+ *cardLink = (*cardLink)->Next;
+ ExFreePool(cardInfo);
+ } else {
+ cardLink = &((*cardLink)->Next);
+ }
+ }
+}
+
+PCARD_INFORMATION
+PipFindCardInformation (
+ PPI_BUS_EXTENSION BusExtension,
+ PSERIAL_IDENTIFIER Id
+ )
+
+/*++
+
+Routine Description:
+
+ The function goes through card list to find the card information structure
+ which matches the caller supplied Id. Note, this routine ignore the card
+ structure flags. So, it may return the card information whcih is marked
+ as invalid.
+ Note the PipMutex must be acquired before calling this routine.
+
+Arguments:
+
+ Id - supplies a pointer to the serial identifier of the card.
+
+Return Value:
+
+ If succeed, the pointer to the card information structure is return.
+ Otherwise a NULL pointer is returned.
+
+--*/
+{
+ PCARD_INFORMATION cardInfo;
+ PSINGLE_LIST_ENTRY cardLink;
+
+ //
+ // Go through the card link list to match the id.
+ //
+
+ cardLink = BusExtension->CardList.Next;
+ while (cardLink) {
+ cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
+ ASSERT (cardInfo->CardData);
+ if (RtlEqualMemory(cardInfo->CardData, Id, sizeof(SERIAL_IDENTIFIER))) {
+ return cardInfo;
+ }
+ cardLink = cardLink->Next;
+ }
+ return NULL;
+}
+
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/busp.h b/private/ntos/nthals/extender/pnpisa/i386/busp.h
new file mode 100644
index 000000000..bef6851ee
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/busp.h
@@ -0,0 +1,576 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ busp.h
+
+Abstract:
+
+ Hardware independent header file for Pnp Isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "stdio.h"
+#include "stdarg.h"
+
+//
+// Structures
+//
+
+//
+// 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]
+
+//
+// CARD_INFORMATION Flags masks
+//
+
+#define CARD_FLAGS_VALID 0x00000001
+
+typedef struct _CARD_INFORMATION_ {
+
+ //
+ // Next points to next CARD_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+ ULONG Flags;
+
+ //
+ // Card select number for this Pnp Isa card.
+ //
+
+ USHORT CardSelectNumber;
+
+ //
+ // Number logical devices in the card.
+ //
+
+ ULONG NumberLogicalDevices;
+
+ //
+ // Logical device link list
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // Pointer to card data which includes:
+ // 9 byte serial identifier for the pnp isa card
+ // PlugPlay Version number type for the pnp isa card
+ // Identifier string resource type for the pnp isa card
+ // Logical device Id resource type (repeat for each logical device)
+ //
+
+ PVOID CardData;
+ ULONG CardDataLength;
+
+} CARD_INFORMATION, *PCARD_INFORMATION;
+
+//
+// DEVICE_INFORMATION Flags masks
+//
+
+#define DEVICE_FLAGS_VALID 0x00000001
+
+typedef struct _DEVICE_INFORMATION_ {
+
+ //
+ // Link list for ALL the Pnp Isa logical devices.
+ // NextDevice points to next DEVICE_INFORMATION structure
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+ ULONG Flags;
+
+ //
+ // Pointer to the CARD_INFORMATION for this device
+ //
+
+ PCARD_INFORMATION CardInformation;
+
+ //
+ // Link list for all the logical devices in a Pnp Isa card.
+ //
+
+ SINGLE_LIST_ENTRY LogicalDeviceList;
+
+ //
+ // LogicalDeviceNumber selects the corresponding logical device in the
+ // pnp isa card specified by CSN.
+ //
+
+ USHORT LogicalDeviceNumber;
+
+ //
+ // DeviceControl in progress flags
+ //
+
+ BOOLEAN SyncBusy;
+
+ //
+ // Pointer to device specific data
+ //
+
+ PUCHAR DeviceData;
+
+ //
+ // Length of the device data
+ //
+
+ ULONG DeviceDataLength;
+
+} DEVICE_INFORMATION, *PDEVICE_INFORMATION;
+
+//
+// Extension data for Bus extender
+//
+
+typedef struct _PI_BUS_EXTENSION {
+
+ //
+ // BusHandler points back to the BUS_HANDLER structure for this extension
+ //
+
+ PBUS_HANDLER BusHandler;
+
+ //
+ // Number of cards selected
+ //
+
+ ULONG NumberCSNs;
+
+ //
+ // ReadDataPort addr
+ //
+
+ PUCHAR ReadDataPort;
+
+ //
+ // Next Slot Number to assign
+ //
+
+ ULONG NextSlotNumber;
+
+ //
+ // Bus Check request list
+ //
+
+ LIST_ENTRY CheckBus;
+
+ //
+ // Device control request list
+ //
+
+ LIST_ENTRY DeviceControl;
+
+ //
+ // DeviceList is the DEVICE_INFORMATION link list.
+ //
+
+ SINGLE_LIST_ENTRY DeviceList;
+
+ //
+ // NoValidSlots is the number of valid slots
+ //
+
+ ULONG NoValidSlots;
+
+ //
+ // CardList is the list of CARD_INFORMATION
+ //
+
+ SINGLE_LIST_ENTRY CardList;
+
+ //
+ // NoValidCards is the number of valid card in the CardList
+ //
+
+// ULONG NoValidCards;
+
+} PI_BUS_EXTENSION, *PPI_BUS_EXTENSION;
+
+typedef struct {
+ BOOLEAN Control;
+} *PBCTL_SET_CONTROL;
+
+//
+// Pnp Bios bus extender device object extension
+//
+
+typedef struct _PI_DEVICE_EXTENSION {
+
+ //
+ // BusHandler points to the BusHandler structure for the bus
+ // extender device object.
+ //
+
+ PBUS_HANDLER BusHandler;
+
+} PI_DEVICE_EXTENSION, *PPI_DEVICE_EXTENSION;
+
+//
+// SlotControl related internal definitions
+//
+
+typedef VOID (* CONTROL_FUNCTION)(PDEVICE_INFORMATION, PHAL_DEVICE_CONTROL_CONTEXT);
+
+typedef struct _DEVICE_CONTROL_HANDLER {
+
+ ULONG ControlCode; // Operation code
+ ULONG MinBuffer; // Minimum buffer requirement for the operation
+ CONTROL_FUNCTION ControlHandler; // Function to do the actual work
+
+} DEVICE_CONTROL_HANDLER, *PDEVICE_CONTROL_HANDLER;
+
+#define NUMBER_DEVICE_CONTROL_FUNCTIONS 11
+
+//
+// Global Data references
+//
+
+extern FAST_MUTEX PipMutex;
+extern FAST_MUTEX PipPortMutex;
+extern KSPIN_LOCK PipSpinlock;
+extern LIST_ENTRY PipControlWorkerList;
+extern LIST_ENTRY PipCheckBusList;
+extern ULONG PipWorkerQueued;
+extern WORK_QUEUE_ITEM PipWorkItem;
+extern ULONG PipNextHandle;
+extern DEVICE_CONTROL_HANDLER PipDeviceControl[];
+extern PDRIVER_OBJECT PipDriverObject;
+extern HAL_CALLBACKS PipHalCallbacks;
+extern PCALLBACK_OBJECT PipEjectCallbackObject;
+extern BOOLEAN PipNoBusyFlag;
+extern PPI_BUS_EXTENSION PipBusExtension;
+extern WCHAR rgzPNPISADeviceName[];
+extern POBJECT_TYPE *IoDeviceHandlerObjectType;
+extern PULONG IoDeviceHandlerObjectSize;
+extern ULONG PipDeviceHandlerObjectSize;
+
+#define DeviceHandler2DeviceInfo(a) ((PDEVICE_INFORMATION) (((PUCHAR) a) + PipDeviceHandlerObjectSize))
+#define DeviceInfo2DeviceHandler(a) ((PDEVICE_HANDLER_OBJECT) (((PUCHAR) a) - PipDeviceHandlerObjectSize))
+#define DeviceInfoSlot(a) (DeviceInfo2DeviceHandler(a)->SlotNumber)
+
+//
+// Prototypes
+//
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+NTSTATUS
+PiAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN PULONG InstanceNumber
+ );
+
+NTSTATUS
+PiCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ );
+
+VOID
+PiUnload (
+ IN PDRIVER_OBJECT DriverObject
+ );
+
+NTSTATUS
+PiReconfigureResources (
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN DRIVER_RECONFIGURE_OPERATION Operation,
+ IN PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ );
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ );
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ );
+
+VOID
+PipStartWorker (
+ VOID
+ );
+
+VOID
+PipQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+VOID
+PipControlWorker (
+ IN PVOID WorkerContext
+ );
+
+VOID
+PipDispatchControl (
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceData
+ );
+
+BOOLEAN
+FASTCALL
+PiBCtlNone (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+BOOLEAN
+FASTCALL
+PiBCtlSync (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceCapabilities (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+VOID
+PiCtlSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+ULONG
+PiGetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PiSetBusData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+PiGetDeviceData (
+ 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
+PiSetDeviceData (
+ 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
+PiQueryBusSlots (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BufferSize,
+ OUT PULONG SlotNumbers,
+ OUT PULONG ReturnedLength
+ );
+
+NTSTATUS
+PiDeviceControl (
+ IN PHAL_DEVICE_CONTROL_CONTEXT Context
+ );
+
+PDEVICE_HANDLER_OBJECT
+PiReferenceDeviceHandler (
+ IN struct _BUS_HANDLER *BusHandler,
+ IN struct _BUS_HANDLER *RootHandler,
+ IN ULONG SlotNumber
+ );
+
+VOID
+PipCheckBus (
+ IN PBUS_HANDLER BusHandler
+ );
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PVOID *ResourceData,
+ OUT PULONG ResourceDataLength
+ );
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ );
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ );
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber
+ );
+
+VOID
+PipLFSRInitiation (
+ VOID
+ );
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs,
+ IN OUT PUCHAR *ReadDataPort
+ );
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ );
+
+VOID
+PipInvalidateCards (
+ IN PPI_BUS_EXTENSION busExtension
+ );
+
+VOID
+PipDeleteCards (
+ IN PPI_BUS_EXTENSION busExtension
+ );
+
+#if DBG
+
+#define DEBUG_MESSAGE 1
+#define DEBUG_BREAK 2
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ );
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ );
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ );
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ );
+
+#define DebugPrint(arg) PipDebugPrint arg
+#else
+#define DebugPrint(arg)
+#endif
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/control.c b/private/ntos/nthals/extender/pnpisa/i386/control.c
new file mode 100644
index 000000000..451a86d91
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/control.c
@@ -0,0 +1,511 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ control.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) Apr-23-1995
+ Most of the code is adapted from PCI bus extender.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+
+VOID
+PipiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceData,
+ PBOOLEAN Sync
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PipControlWorker)
+#pragma alloc_text(PAGE,PipCompleteDeviceControl)
+#endif
+
+VOID
+PipStartWorker (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used to start a worker thread.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG workerQueued;
+
+ if (!PipWorkerQueued) {
+ workerQueued = ExInterlockedExchangeUlong (
+ &PipWorkerQueued,
+ 1,
+ PipSpinLock
+ );
+
+ if (!workerQueued) {
+ ExQueueWorkItem (&PipWorkItem, DelayedWorkQueue);
+ }
+ }
+}
+
+VOID
+PipQueueCheckBus (
+ IN PBUS_HANDLER BusHandler
+ )
+/*++
+
+Routine Description:
+
+ This function enqueues Bus check request to buscheck list.
+
+Arguments:
+
+ BusHandler - supplies a pointer to the bus handler of the bus to be checked.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ExInterlockedInsertTailList (
+ &PipCheckBusList,
+ &((PPI_BUS_EXTENSION)BusHandler->BusData)->CheckBus,
+ &PipSpinlock
+ );
+
+ PipStartWorker();
+}
+
+VOID
+PipControlWorker (
+ IN PVOID WorkerContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by a system worker thread.
+
+ The worker thread dequeues any SlotControls which need to be
+ processed and dispatches them.
+
+ It then checks for any check bus request.
+
+Arguments:
+
+ WorkerContext - supplies a pointer to a context for the worker. Here
+ it is always NULL.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PLIST_ENTRY entry;
+ PPI_BUS_EXTENSION busExtension;
+ PHAL_DEVICE_CONTROL_CONTEXT context;
+
+ PAGED_CODE ();
+
+ //
+ // process check bus
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &PipCheckBusList,
+ &PipSpinlock
+ );
+
+ if (!entry) {
+ break;
+ }
+ busExtension = CONTAINING_RECORD (
+ entry,
+ PI_BUS_EXTENSION,
+ CheckBus
+ );
+
+ PipCheckBus (busExtension->BusHandler);
+ }
+
+ //
+ // Reset worker item for next time
+ //
+
+ ExInitializeWorkItem (&PipWorkItem, PipControlWorker, NULL);
+ ExInterlockedExchangeUlong (&PipWorkerQueued, 0, PipSpinLock);
+
+ //
+ // Dispatch pending device controls
+ //
+
+ for (; ;) {
+ entry = ExInterlockedRemoveHeadList (
+ &PipControlWorkerList,
+ &PipSpinlock
+ );
+
+ if (!entry) {
+
+ //
+ // All done, exit the loop.
+ //
+
+ break;
+ }
+
+ context = CONTAINING_RECORD (
+ entry,
+ HAL_DEVICE_CONTROL_CONTEXT,
+ ContextWorkQueue,
+ );
+
+ PipDispatchControl (context);
+ }
+}
+
+VOID
+PipDispatchControl (
+ 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:
+
+ None.
+
+--*/
+{
+ PDEVICE_CONTROL_HANDLER deviceControlHandler;
+ PPI_BUS_EXTENSION busExtension;
+ PDEVICE_INFORMATION deviceInfo;
+ KIRQL oldIrql;
+ BOOLEAN enqueueIt;
+ PLIST_ENTRY link;
+
+ deviceControlHandler = (PDEVICE_CONTROL_HANDLER) Context->ContextControlHandler;
+ deviceInfo = DeviceHandler2DeviceInfo (Context->DeviceControl.DeviceHandler);
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ ExAcquireFastMutex(&PipMutex);
+
+ //
+ // Verify the device data is still valid
+ //
+
+ if (!(deviceInfo->Flags & DEVICE_FLAGS_VALID)) {
+
+ //
+ // Caller has invalid handle, or handle to a different device
+ //
+
+ DebugPrint ((DEBUG_MESSAGE, "PnpIsa: DeviceControl has invalid device handler \n" ));
+ Context->DeviceControl.Status = STATUS_NO_SUCH_DEVICE;
+ ExReleaseFastMutex(&PipMutex);
+ HalCompleteDeviceControl (Context);
+ return ;
+ }
+ busExtension = (PPI_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Check to see if this request can be begun now
+ //
+
+ link = (PLIST_ENTRY) &Context->ContextWorkQueue;
+ enqueueIt = PiBCtlSync (deviceInfo, Context);
+
+ if (enqueueIt) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ KeAcquireSpinLock (&PipSpinlock, &oldIrql);
+ InsertTailList (&busExtension->DeviceControl, link);
+ KeReleaseSpinLock (&PipSpinlock, oldIrql);
+ ExReleaseFastMutex(&PipMutex);
+ return ;
+ }
+
+ //
+ // Dispatch the function to it's handler
+ //
+
+ ExReleaseFastMutex(&PipMutex);
+ deviceControlHandler->ControlHandler (deviceInfo, Context);
+}
+
+VOID
+PipiCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceInfo,
+ PBOOLEAN Sync
+ )
+/*++
+
+Routine Description:
+
+ This function is used to complete a SlotControl. If another SlotControl
+ was delayed on this device, this function will dispatch them
+
+Arguments:
+
+ Status - supplies a NTSTATUS code for the completion.
+
+ Context - supplies a pointer to the original device control context.
+
+ DeviceInfo - supplies a pointer to the device info structure to be completed.
+
+ Sync - supplies a BOOLEAN variable to indicate
+
+Return Value:
+
+--*/
+{
+ KIRQL oldIrql;
+ PLIST_ENTRY link;
+ PBOOLEAN busyFlag;
+ BOOLEAN startWorker = FALSE;
+ PPI_BUS_EXTENSION busExtension;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ busyFlag = (PBOOLEAN) Context->ContextBusyFlag;
+ deviceHandler = DeviceInfo2DeviceHandler(DeviceInfo);
+ busExtension = (PPI_BUS_EXTENSION)Context->Handler->BusData;
+
+ //
+ // Pass it to the hal for completion
+ //
+
+ Context->DeviceControl.Status = Status;
+ HalCompleteDeviceControl (Context);
+
+ //
+ // Get access to the slot specific data.
+ //
+
+ KeAcquireSpinLock (&PipSpinlock, &oldIrql);
+
+ //
+ // Clear appropiate busy flag
+ //
+
+ *busyFlag = FALSE;
+
+ //
+ // Check to see if there are any pending device controls for
+ // this device. If so, requeue them to the worker thread
+ //
+
+ for (link = busExtension->DeviceControl.Flink;
+ link != &busExtension->DeviceControl;
+ link = link->Flink) {
+
+ Context = CONTAINING_RECORD (link, HAL_DEVICE_CONTROL_CONTEXT, ContextWorkQueue);
+ if (Context->DeviceControl.DeviceHandler == deviceHandler) {
+ RemoveEntryList (link);
+ InsertTailList (&PipControlWorkerList, link);
+ startWorker = TRUE;
+ break;
+ }
+ }
+
+ KeReleaseSpinLock (&PipSpinlock, oldIrql);
+
+ if (startWorker) {
+ PipStartWorker ();
+ }
+}
+
+VOID
+PipCompleteDeviceControl (
+ NTSTATUS Status,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PDEVICE_INFORMATION DeviceInfo
+ )
+/*++
+
+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();
+
+ PipiCompleteDeviceControl (
+ Status,
+ Context,
+ DeviceInfo,
+ &DeviceInfo->SyncBusy
+ );
+}
+
+BOOLEAN
+FASTCALL
+PiBCtlNone (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to indicate there is no synchronization for this
+ device control function.
+
+Arguments:
+
+ Context - supplies a pointer to the device control context.
+
+ DeviceInfo - supplies a pointer to the device data to be completed.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // No synchronization needed for this SlotControl
+ //
+
+ Context->ContextBusyFlag = (ULONG) &PipNoBusyFlag;
+ return FALSE;
+}
+
+BOOLEAN
+FASTCALL
+PiBCtlSync (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to synchronize device control request. it checks the
+ state (busy/not busy) of the slot and returns a boolean flag to indicate
+ whether the request can be serviced immediately or it needs to be enqueued for
+ later processing.
+
+Arguments:
+
+ DeviceInfo - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ A boolean value to indicate if the request needs to be enqueued for later
+ processing.
+
+--*/
+{
+ //
+ // This is a sync command, verify the slot is not busy with a different
+ // command.
+ //
+
+ if (DeviceInfo->SyncBusy) {
+
+ //
+ // Enqueue this command to be handled when the slot is no longer busy.
+ //
+
+ return TRUE;
+ }
+
+ //
+ // Don't enqueue, dispatch it now
+ //
+
+ DeviceInfo->SyncBusy = TRUE;
+ Context->ContextBusyFlag = (ULONG) &DeviceInfo->SyncBusy;
+ return FALSE;
+}
+
+VOID
+PiCtlQueryDeviceCapabilities (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the BCTL_DEVICE_CAPABILITIES structure to the caller
+ specified buffer.
+
+Arguments:
+
+ DeviceInfo - supplies a pointer to the device data to be completed.
+
+ Context - supplies a pointer to the device control context.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PBCTL_DEVICE_CAPABILITIES capabilities;
+
+ capabilities = (PBCTL_DEVICE_CAPABILITIES) Context->DeviceControl.Buffer;
+
+ capabilities->PowerSupported = FALSE;
+ capabilities->ResumeSupported = FALSE;
+ capabilities->LockSupported = FALSE;
+ capabilities->EjectSupported = FALSE;
+ PipCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceInfo);
+}
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/convert.c b/private/ntos/nthals/extender/pnpisa/i386/convert.c
new file mode 100644
index 000000000..36cf35f99
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/convert.c
@@ -0,0 +1,1077 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xlate.c
+
+Abstract:
+
+ This file contains routines to translate resources between PnP ISA/BIOS
+ format and Windows NT formats.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 12-Apr-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "..\..\pnpbios\i386\pbios.h"
+
+//
+// internal structures for resource translation
+//
+
+typedef struct _PB_DEPENDENT_RESOURCES {
+ ULONG Count;
+ UCHAR Flags;
+ UCHAR Priority;
+ struct _PB_DEPENDENT_RESOURCES *Next;
+} PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
+
+#define DEPENDENT_FLAGS_END 1
+
+typedef struct _PB_ATERNATIVE_INFORMATION {
+ PPB_DEPENDENT_RESOURCES Resources;
+ ULONG NoDependentFunctions;
+ ULONG TotalResourceCount;
+} PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
+
+//
+// Internal function references
+//
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ );
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ );
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ );
+
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(PAGE,PbBiosResourcesToNtResources)
+#pragma alloc_text(PAGE,PbIoDescriptorToCmDescriptor)
+#pragma alloc_text(PAGE,PbAddDependentResourcesToList)
+#pragma alloc_text(PAGE,PbBiosIrqToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosDmaToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortFixedToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosPortToIoDescriptor)
+#pragma alloc_text(PAGE,PbBiosMemoryToIoDescriptor)
+#endif
+
+NTSTATUS
+PbBiosResourcesToNtResources (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PUCHAR *BiosData,
+ OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList,
+ OUT PULONG ReturnedLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine parses the Bios resource list and generates
+ a NT resource list. The returned Nt resource list could be either IO
+ format or CM format. It is caller's responsibility to release the
+ returned data buffer.
+
+Arguments:
+
+ SlotNumber - specifies the slot number of the BIOS resource.
+
+ BiosData - Supplies a pointer to a variable which specifies the bios resource
+ data buffer and which to receive the pointer to next bios resource data.
+
+ ReturnedList - supplies a variable to receive the desired resource list.
+
+ ReturnedLength - Supplies a variable to receive the length of the resource list.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ PUCHAR buffer;
+ USHORT mask16, increment;
+ UCHAR tagName, mask8;
+ NTSTATUS status;
+ PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
+ ULONG commonResCount = 0, dependDescCount = 0, i, j;
+ ULONG alternativeListCount = 0, dependFunctionCount = 0;
+ PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
+ PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
+ BOOLEAN dependent = FALSE;
+ ULONG listSize, noResLists;
+ ULONG totalDescCount, descCount;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
+ PIO_RESOURCE_LIST ioResList;
+
+ //
+ // First, scan the bios data to determine the memory requirement and
+ // the information to build internal data structures.
+ //
+
+ *ReturnedLength = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ while (tagName != TAG_COMPLETE_END) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ tagName &= SMALL_TAG_MASK;
+ } else {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ }
+
+ //
+ // Based on the type of the BIOS resource, determine the count of
+ // the IO descriptors.
+ //
+
+ switch (tagName) {
+ case TAG_IRQ:
+ mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
+ i = 0;
+ while (mask16) {
+ if (mask16 & 1) {
+ i++;
+ }
+ mask16 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_DMA:
+ mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
+ i = 0;
+ while (mask8) {
+ if (mask8 & 1) {
+ i++;
+ }
+ mask8 >>= 1;
+ }
+ if (!dependent) {
+ commonResCount += i;
+ } else {
+ dependDescCount += i;
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ dependFunctionCount++;
+ break;
+ case TAG_END_DEPEND:
+ dependent = FALSE;
+ alternativeListCount++;
+ break;
+ case TAG_IO_FIXED:
+ case TAG_IO:
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (!dependent) {
+ commonResCount++;
+ } else {
+ dependDescCount++;
+ }
+ break;
+ default:
+
+ //
+ // Unknown tag. Skip it.
+ //
+
+ break;
+ }
+
+ //
+ // Move to next bios resource descriptor.
+ //
+
+ buffer += increment;
+ tagName = *buffer;
+ }
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (commonResCount == 0 && dependFunctionCount == 0) {
+ *ReturnedList = NULL;
+ *ReturnedLength = 0;
+ *BiosData = buffer + 2;
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Allocate memory for our internal data structures
+ //
+
+ if (dependFunctionCount) {
+ dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
+ PagedPool,
+ dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
+ dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
+ 'bPnP'
+ );
+ if (!dependResources) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ dependResList = dependResources; // remember it so we can free it.
+ }
+
+ if (alternativeListCount) {
+ ASSERT(dependFunctionCount != 0);
+ alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
+ 'bPnP'
+ );
+ if (!alternativeList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit0;
+ }
+ RtlZeroMemory(alternativeList,
+ sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
+ );
+ alternativeList[0].Resources = dependResources;
+ }
+ if (commonResCount) {
+ commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
+ PagedPool,
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
+ 'bPnP'
+ );
+ if (!commonResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit1;
+ }
+ }
+
+ //
+ // Now start over again to process the bios data and initialize our internal
+ // resource representation.
+ //
+
+ commonIoDesc = commonResources;
+ dependDescCount = 0;
+ alternativeListCount = 0;
+ buffer = *BiosData;
+ tagName = *buffer;
+ dependent = FALSE;
+ while (tagName != TAG_COMPLETE_END) {
+ if (!(tagName & LARGE_RESOURCE_TAG)) {
+ tagName &= SMALL_TAG_MASK;
+ }
+ switch (tagName) {
+ case TAG_IRQ:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_DMA:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_START_DEPEND:
+ dependent = TRUE;
+ alternativeList[alternativeListCount].NoDependentFunctions++;
+ if (dependDescCount != 0) {
+
+ //
+ // End of current dependent function
+ //
+
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = 0;
+ dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = dependResources->Next;
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ }
+ if (*buffer & SMALL_TAG_SIZE_MASK) {
+ dependResources->Priority = *(buffer + 1);
+ }
+ dependDescCount = 0;
+ dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
+ buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
+ break;
+ case TAG_END_DEPEND:
+ alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
+ dependResources->Count = dependDescCount;
+ dependResources->Flags = DEPENDENT_FLAGS_END;
+ dependResources->Next = alternativeList[alternativeListCount].Resources;
+ dependent = FALSE;
+ dependDescCount = 0;
+ alternativeListCount++;
+ alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
+ dependResources = alternativeList[alternativeListCount].Resources;
+ buffer++;
+ break;
+ case TAG_IO:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_IO_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ case TAG_MEMORY:
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ if (dependent) {
+ ioDesc = dependIoDesc;
+ dependDescCount;
+ } else {
+ ioDesc = commonIoDesc;
+ }
+ status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
+ if (NT_SUCCESS(status)) {
+ if (dependent) {
+ dependIoDesc++;
+ dependDescCount++;
+ } else {
+ commonIoDesc++;
+ }
+ }
+ break;
+ default:
+
+ //
+ // Don't-care tag simpley advance the buffer pointer to next tag.
+ //
+
+ if (*buffer & LARGE_RESOURCE_TAG) {
+ increment = *(PUSHORT)(buffer+1);
+ increment += 3; // length of large tag
+ } else {
+ increment = (USHORT)(*buffer & SMALL_TAG_SIZE_MASK);
+ increment += 1; // length of small tag
+ }
+ buffer += increment;
+ }
+ tagName = *buffer;
+ }
+
+ if (alternativeListCount != 0) {
+ alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
+ }
+ *BiosData = buffer + 2; // Skip END_TAG
+
+ //
+ // prepare IoResourceList
+ //
+
+ noResLists = 1;
+ for (i = 0; i < alternativeListCount; i++) {
+ noResLists *= alternativeList[i].NoDependentFunctions;
+ }
+ totalDescCount = 0;
+ for (i = 0; i < alternativeListCount; i++) {
+ descCount = 1;
+ for (j = 0; j < alternativeListCount; j++) {
+ if (j == i) {
+ descCount *= alternativeList[j].TotalResourceCount;
+ } else {
+ descCount *= alternativeList[j].NoDependentFunctions;
+ }
+ }
+ totalDescCount += descCount;
+ }
+ listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
+ sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
+ sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
+
+ ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
+ if (!ioResReqList) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit2;
+ }
+
+ ioResReqList->ListSize = listSize;
+ ioResReqList->InterfaceType = Internal;
+ ioResReqList->BusNumber = BusNumber;
+ ioResReqList->SlotNumber = SlotNumber;
+ ioResReqList->Reserved[0] = 0;
+ ioResReqList->Reserved[1] = 0;
+ ioResReqList->Reserved[2] = 0;
+ ioResReqList->AlternativeLists = noResLists;
+ ioResList = &ioResReqList->List[0];
+
+ //
+ // Build resource lists
+ //
+
+ for (i = 0; i < noResLists; i++) {
+ ULONG size;
+
+ ioResList->Version = 1;
+ ioResList->Revision = 1;
+ buffer = (PUCHAR)&ioResList->Descriptors[0];
+
+ //
+ // Copy common resources to the list
+ //
+
+ if (commonResources) {
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
+ RtlMoveMemory(buffer, commonResources, size);
+ buffer += size;
+ }
+
+ //
+ // Copy dependent functions if any.
+ //
+
+ if (alternativeList) {
+ PbAddDependentResourcesToList(&buffer, 0, alternativeList);
+ }
+
+ //
+ // Update io resource list ptr
+ //
+
+ ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
+ sizeof(IO_RESOURCE_DESCRIPTOR);
+ ioResList = (PIO_RESOURCE_LIST)buffer;
+ }
+
+ *ReturnedLength = listSize;
+ status = STATUS_SUCCESS;
+ *ReturnedList = ioResReqList;
+exit2:
+ if (commonResources) {
+ ExFreePool(commonResources);
+ }
+exit1:
+ if (alternativeList) {
+ ExFreePool(alternativeList);
+ }
+exit0:
+ if (dependResList) {
+ ExFreePool(dependResList);
+ }
+ return status;
+}
+
+PPB_DEPENDENT_RESOURCES
+PbAddDependentResourcesToList (
+ IN OUT PUCHAR *ResourceDescriptor,
+ IN ULONG ListNo,
+ IN PPB_ALTERNATIVE_INFORMATION AlternativeList
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds dependent functions to caller specified list.
+
+Arguments:
+
+ ResourceDescriptor - supplies a pointer to the descriptor buffer.
+
+ ListNo - supplies an index to the AlternativeList.
+
+ AlternativeList - supplies a pointer to the alternativelist array.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPB_DEPENDENT_RESOURCES dependentResources, ptr;
+ ULONG size;
+
+ //
+ // Copy dependent resources to caller supplied list buffer and
+ // update the list buffer pointer.
+ //
+
+ dependentResources = AlternativeList[ListNo].Resources;
+ size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
+ RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
+ *ResourceDescriptor = *ResourceDescriptor + size;
+
+ //
+ // Add dependent resource of next list to caller's buffer
+ //
+
+ if (AlternativeList[ListNo + 1].Resources) {
+ ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
+ } else {
+ ptr = NULL;
+ }
+ if (ptr == NULL) {
+ AlternativeList[ListNo].Resources = dependentResources->Next;
+ if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
+ ptr = dependentResources->Next;
+ }
+ }
+ return ptr;
+}
+
+VOID
+PbIoDescriptorToCmDescriptor (
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Arguments:
+
+ IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
+
+ CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CmDescriptor->Type = IoDescriptor->Type;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ switch (CmDescriptor->Type) {
+ case CmResourceTypePort:
+ CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
+ CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
+ break;
+ case CmResourceTypeInterrupt:
+ CmDescriptor->u.Interrupt.Level =
+ CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
+ CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
+ break;
+ case CmResourceTypeMemory:
+ CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+ CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
+ break;
+ case CmResourceTypeDma:
+ CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
+ CmDescriptor->u.Dma.Port = 0;
+ CmDescriptor->u.Dma.Reserved1 = 0;
+ break;
+ }
+}
+
+NTSTATUS
+PbBiosIrqToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IRQ information to NT usable format.
+ This routine stops when an irq io resource is generated. if there are
+ more irq io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ USHORT mask;
+ ULONG irq;
+ PPNP_IRQ_DESCRIPTOR buffer;
+ UCHAR size, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ size = buffer->Tag & SMALL_TAG_SIZE_MASK;
+ mask = buffer->IrqMask;
+ mask >>= bitPosition;
+ irq = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ irq = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (irq != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeInterrupt;
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (size == 3 && buffer->Information & 0x0C) {
+ IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ IoDescriptor->ShareDisposition = CmResourceShareShared;
+ }
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Interrupt.MinimumVector = irq;
+ IoDescriptor->u.Interrupt.MaximumVector = irq;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current irq tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ *BiosData = (PUCHAR)buffer + size + 1;
+ return status;
+}
+
+NTSTATUS
+PbBiosDmaToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS DMA information to NT usable format.
+ This routine stops when an dma io resource is generated. if there are
+ more dma io resource descriptors available, the BiosData pointer will
+ not advance. So caller will pass us the same resource tag again.
+
+ Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
+ for each seperated channel required.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ static ULONG bitPosition = 0;
+ ULONG dma;
+ PPNP_DMA_DESCRIPTOR buffer;
+ UCHAR mask, option;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
+
+ //
+ // if this is not the first descriptor for the tag, set
+ // its option to alternative.
+ //
+
+ if (bitPosition == 0) {
+ option = 0;
+ } else {
+ option = IO_RESOURCE_ALTERNATIVE;
+ }
+ mask = buffer->ChannelMask;
+ mask >>= bitPosition;
+ dma = (ULONG) -1;
+
+ while (mask) {
+ if (mask & 1) {
+ dma = bitPosition;
+ break;
+ }
+ mask >>= 1;
+ bitPosition++;
+ }
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ if (dma != (ULONG)-1) {
+ IoDescriptor->Option = option;
+ IoDescriptor->Type = CmResourceTypeDma;
+ IoDescriptor->Flags = 0;
+ IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Dma.MinimumChannel = dma;
+ IoDescriptor->u.Dma.MaximumChannel = dma;
+ } else {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(status)) {
+
+ //
+ // try to move bitPosition to next 1 bit.
+ //
+
+ while (mask) {
+ mask >>= 1;
+ bitPosition++;
+ if (mask & 1) {
+ return status;
+ }
+ }
+ }
+
+ //
+ // Done with current dma tag, advance pointer to next tag
+ //
+
+ bitPosition = 0;
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return status;
+}
+
+NTSTATUS
+PbBiosPortFixedToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS FIXED IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_FIXED_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = 1;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosPortToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS IO information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PPNP_PORT_DESCRIPTOR buffer;
+
+ buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
+
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypePort;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
+ IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
+ IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
+ IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
+ IoDescriptor->u.Port.Length - 1;
+ IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
+ IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
+
+ //
+ // Done with current fixed port tag, advance pointer to next tag
+ //
+
+ buffer += 1;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PbBiosMemoryToIoDescriptor (
+ IN OUT PUCHAR *BiosData,
+ IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates BIOS MEMORY information to NT usable format.
+
+Arguments:
+
+ BiosData - Supplies a pointer to the bios resource data buffer.
+
+ IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
+ Converted resource will be stored here.
+
+Return Value:
+
+ return NTSTATUS code to indicate the result of the operation.
+
+--*/
+{
+ PUCHAR buffer;
+ UCHAR tag;
+ PHYSICAL_ADDRESS minAddr, maxAddr;
+ ULONG alignment, length;
+ USHORT increment;
+
+ buffer = *BiosData;
+ tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
+ increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
+
+ minAddr.HighPart = 0;
+ maxAddr.HighPart = 0;
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
+ if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
+ alignment = 0x10000;
+ }
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
+ maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
+ maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
+ alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
+ minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
+ maxAddr.LowPart = minAddr.LowPart + length - 1;
+ alignment = 1;
+ break;
+ }
+ //
+ // Fill in Io resource descriptor
+ //
+
+ IoDescriptor->Option = 0;
+ IoDescriptor->Type = CmResourceTypeMemory;
+ IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
+ IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ IoDescriptor->Spare1 = 0;
+ IoDescriptor->Spare2 = 0;
+ IoDescriptor->u.Memory.MinimumAddress = minAddr;
+ IoDescriptor->u.Memory.MaximumAddress = maxAddr;
+ IoDescriptor->u.Memory.Alignment = alignment;
+ IoDescriptor->u.Memory.Length = length;
+
+ //
+ // Done with current tag, advance pointer to next tag
+ //
+
+ buffer += increment;
+ *BiosData = (PUCHAR)buffer;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pnpisa/i386/data.c b/private/ntos/nthals/extender/pnpisa/i386/data.c
new file mode 100644
index 000000000..be0a9a08f
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/data.c
@@ -0,0 +1,156 @@
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pbdata.c
+
+Abstract:
+
+ Declares various data which is specific to PNP ISA bus extender architecture and
+ is independent of BIOS.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-26-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+
+//
+// PipMutex - To synchronize with device handle changes
+//
+
+FAST_MUTEX PipMutex;
+
+//
+// PipPortMutex - To synchronize with Read data port access.
+// Note, you can *not* ask for PipMutex while owning PipPortMutex.
+//
+
+FAST_MUTEX PipPortMutex;
+
+//
+// PipSpinLock - Lock to protect DeviceControl globals
+//
+
+KSPIN_LOCK PipSpinlock;
+
+//
+// PipControlWorkerList - List of device control's which are pending for worker thread
+//
+
+LIST_ENTRY PipControlWorkerList;
+ULONG PipWorkerQueued;
+
+//
+// PipWorkItem - Enqueue for DeviceControl worker thread
+//
+
+WORK_QUEUE_ITEM PipWorkItem;
+
+//
+// PipCheckBusList - List to enqueue bus check request
+//
+
+LIST_ENTRY PipCheckBusList;
+
+//
+// Eject callback object
+//
+
+PCALLBACK_OBJECT PipEjectCallbackObject;
+
+//
+// regPNPISADeviceName
+//
+
+WCHAR rgzPNPISADeviceName[] = L"\\Device\\PnpIsa_%d";
+
+//
+// Size of DeviceHandlerObject
+//
+
+ULONG PipDeviceHandlerObjectSize;
+
+//
+// DeviceControl dispatch table
+//
+
+#define B_EJECT BCTL_EJECT
+#define B_UID BCTL_QUERY_DEVICE_UNIQUE_ID
+#define B_CAPABILITIES BCTL_QUERY_DEVICE_CAPABILITIES
+#define B_ID BCTL_QUERY_DEVICE_ID
+#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
+
+//
+// declare slot control function table.
+// NOTE if the number of entries is changed, the NUMBER_SLOT_CONTROL_FUNCTIONS defined in
+// busp.h must be chnaged accordingly.
+//
+
+DEVICE_CONTROL_HANDLER PipDeviceControl[] = {
+ B_EJECT, 0, NULL,
+ B_ID, 32, PiCtlQueryDeviceId,
+ B_UID, 32, PiCtlQueryDeviceUniqueId,
+ B_CAPABILITIES, sizeof(BCTL_DEVICE_CAPABILITIES), PiCtlQueryDeviceCapabilities,
+ B_RES, sizeof(ULONG), PiCtlQueryDeviceResources,
+ B_RES_REQ, sizeof(ULONG), PiCtlQueryDeviceResourceRequirements,
+ B_QUERY_EJECT, sizeof(PVOID), NULL,
+ B_SET_LOCK, sizeof(BOOLEAN), NULL,
+ B_SET_RESUME, sizeof(BOOLEAN), NULL,
+ B_SET_POWER, sizeof(POWER_STATE), NULL,
+ B_SET_RES, 0, PiCtlSetDeviceResources,
+};
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("PAGE")
+#endif
+
+//
+// Bus Extender driver object
+//
+
+PDRIVER_OBJECT PipDriverObject;
+
+//
+// Pointers to Hal callback objects
+//
+
+HAL_CALLBACKS PipHalCallbacks;
+
+//
+// PipNoBusyFlag - scratch memory location to point at
+//
+
+BOOLEAN PipNoBusyFlag;
+
+//
+// Pointers to bus extension data.
+//
+
+PPI_BUS_EXTENSION PipBusExtension;
+
+//
+// Read_data_port address
+// (This is mainly for convinience. It duplicates the
+// ReadDataPort field in BUS extension structure.)
+//
+
+PUCHAR PipReadDataPort;
diff --git a/private/ntos/nthals/extender/pnpisa/i386/init.c b/private/ntos/nthals/extender/pnpisa/i386/init.c
new file mode 100644
index 000000000..68108ed7c
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/init.c
@@ -0,0 +1,506 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+ DriverEntry initialization code for pnp isa bus extender.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 3-Aug-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+NTSTATUS
+PiInstallBusHandler (
+ IN PBUS_HANDLER PiBus
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,DriverEntry)
+#pragma alloc_text(PAGE,PiAddBusDevices)
+#pragma alloc_text(PAGE,PiInstallBusHandler)
+#endif
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks if pnp isa bus exists. if yes, it builds and
+ initializes pnp isa card information and its associated device information
+ structure.
+
+Arguments:
+
+ DriverObject - specifies the driver object for the bus extender.
+
+ RegistryPath - supplies a pointer to a unicode string of the service key name in
+ the CurrentControlSet\Services key for the bus extender.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PVOID p;
+ PHAL_BUS_INFORMATION pBusInfo;
+ HAL_BUS_INFORMATION busInfo;
+ ULONG length, i, bufferSize, count;
+ PCM_RESOURCE_LIST configuration = NULL;
+ ULONG deviceFlags;
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+
+ //
+ // First make sure this is the only pnp Isa bus extender running in the system.
+ //
+
+ status = HalQuerySystemInformation (
+ HalInstalledBusInformation,
+ 0,
+ pBusInfo,
+ &length
+ );
+tryAgain:
+ if (status == STATUS_BUFFER_TOO_SMALL) {
+ pBusInfo = ExAllocatePool(PagedPool, length);
+ if (pBusInfo == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to query installed bus info.\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+ status = HalQuerySystemInformation (
+ HalInstalledBusInformation,
+ length,
+ pBusInfo,
+ &length
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // We need to check the buffer size again. It is possible another bus was added
+ // between the two HalQuerySystemInformation calls. In this case, the buffer
+ // requirement is changed.
+ //
+
+ if (status == STATUS_BUFFER_TOO_SMALL) {
+ ExFreePool(pBusInfo);
+ goto tryAgain;
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to query installed bus info.\n"));
+ return status;
+ }
+ }
+
+ //
+ // Check installed bus information to make sure there is no existing Pnp Isa
+ // bus extender.
+ //
+
+ p = pBusInfo;
+ for (i = 0; i < length / sizeof(HAL_BUS_INFORMATION); i++, pBusInfo++) {
+ if (pBusInfo->BusType == PNPISABus &&
+ pBusInfo->ConfigurationType == PNPISAConfiguration) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: A Pnp Isa bus extender is currently running in the system.\n"));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ ExFreePool(p);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ //
+ // Get pointers to the Hals callback objects. The one we are really interested
+ // in is Bus Check callback.
+ //
+
+ status = HalQuerySystemInformation (
+ HalCallbackInformation,
+ sizeof (PipHalCallbacks),
+ &PipHalCallbacks,
+ &length
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to query Hal callbacks\n"));
+ return status;
+ }
+
+ //
+ // Initialize globals
+ //
+
+ PipDriverObject = DriverObject;
+ ExInitializeWorkItem (&PipWorkItem, PipControlWorker, NULL);
+ KeInitializeSpinLock (&PipSpinlock);
+ InitializeListHead (&PipControlWorkerList);
+ InitializeListHead (&PipCheckBusList);
+ ExInitializeFastMutex (&PipMutex);
+ ExInitializeFastMutex (&PipPortMutex);
+ PipDeviceHandlerObjectSize = *IoDeviceHandlerObjectSize;
+
+ //
+ // Initialize driver object add and detect device entries.
+ //
+
+ DriverObject->DriverExtension->AddDevice = PiAddBusDevices;
+ DriverObject->DriverExtension->ReconfigureDevice = PiReconfigureResources;
+ DriverObject->DriverUnload = PiUnload;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = PiCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = PiCreateClose;
+ //
+ // Query the devices/buses currently controlled by the bus extender
+ //
+
+ status = IoQueryDeviceEnumInfo (&DriverObject->DriverExtension->ServiceKeyName, &count);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ ASSERT(count == 0 || count == 1);
+ for (i = 0; i < count; i++) {
+ status = IoGetDeviceHandler(&DriverObject->DriverExtension->ServiceKeyName,
+ i,
+ &deviceHandler);
+ if (NT_SUCCESS(status)) {
+ bufferSize = sizeof(CM_RESOURCE_LIST);
+tryAgain1:
+ configuration = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool,
+ bufferSize
+ );
+ if (!configuration) {
+ IoReleaseDeviceHandler(deviceHandler);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ status = IoQueryDeviceConfiguration(deviceHandler,
+ &busInfo,
+ &deviceFlags,
+ configuration,
+ bufferSize, // buffer size
+ &length // Actual size
+ );
+ if (NT_SUCCESS(status)) {
+
+ IoReleaseDeviceHandler(deviceHandler);
+
+ //
+ // We know we have two buses at most. If this is the first bus, we will add it
+ // and exit. We don't touch 2nd bus at init time. It should be enumerated
+ // later.
+
+ if (configuration->List[0].BusNumber == 0 &&
+ configuration->List[0].InterfaceType == PNPISABus) {
+ if (deviceFlags == DeviceStatusOK) {
+ PiAddBusDevices(&DriverObject->DriverExtension->ServiceKeyName, &i);
+ ExFreePool(configuration);
+ break;
+ }
+ }
+ } else if (status == STATUS_BUFFER_TOO_SMALL) {
+ ExFreePool(configuration);
+ bufferSize = length;
+ goto tryAgain1;
+ }
+ ExFreePool(configuration);
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PiAddBusDevices(
+ IN PUNICODE_STRING ServiceKeyName,
+ IN PULONG InstanceNumber
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ NTSTATUS status;
+ PBUS_HANDLER busHandler;
+ HAL_BUS_INFORMATION busInfo;
+ ULONG deviceInstanceFlags, actualSize;
+ PCM_RESOURCE_LIST detectSignature;
+ UCHAR configuration[sizeof(CM_RESOURCE_LIST)];
+ UNICODE_STRING unicodeString;
+ WCHAR buffer[60];
+ PDEVICE_HANDLER_OBJECT deviceHandler;
+ IO_RESOURCE_REQUIREMENTS_LIST ioResource;
+ PCM_RESOURCE_LIST cmResource;
+ PWSTR str;
+
+ PAGED_CODE();
+
+ //
+ // Check if DriverEntry succeeded and if the Pnp Isa bus has been
+ // added already. (There is ONE and only one Pnp Isa bus)
+ //
+
+ if (!PipDriverObject || (PipBusExtension && PipBusExtension->ReadDataPort)) {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ //
+ // Register bus handler for Pnp Isa bus
+ //
+
+ status = HalRegisterBusHandler (
+ PNPISABus,
+ PNPISAConfiguration,
+ (ULONG)-1,
+ Internal,
+ 0,
+ sizeof (PI_BUS_EXTENSION),
+ PiInstallBusHandler,
+ &busHandler
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Register Pnp bus handler failed\n"));
+ return status;
+ }
+
+ if (*InstanceNumber == PLUGPLAY_NO_INSTANCE) {
+
+ //
+ // Register the bus with Pnp manager as a detected bus.
+ //
+
+ RtlZeroMemory(configuration, sizeof(CM_RESOURCE_LIST));
+ detectSignature = (PCM_RESOURCE_LIST)configuration;
+ detectSignature->Count = 1;
+ detectSignature->List[0].InterfaceType = PNPISABus;
+ detectSignature->List[0].BusNumber = 0;
+ status = IoRegisterDetectedDevice (ServiceKeyName, detectSignature, InstanceNumber);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_BREAK,"PnpIsa: Failed to register bus as detected bus\n"));
+ goto errorExit;
+ }
+ }
+
+ //
+ // Call Pnp Io Mgr to register the new device object path
+ //
+
+ swprintf (buffer, rgzPNPISADeviceName, busHandler->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ if (!NT_SUCCESS(status = IoGetDeviceHandler(&PipDriverObject->DriverExtension->ServiceKeyName,
+ *InstanceNumber, &deviceHandler)) ||
+ !NT_SUCCESS(status = IoRegisterDevicePath(deviceHandler, &unicodeString, TRUE, NULL,
+ DeviceStatusOK))) {
+
+ //
+ // BUGBUG - unregister bus handler? How?
+ //
+
+ if (deviceHandler) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Register NT device path failed\n"));
+ IoReleaseDeviceHandler(deviceHandler);
+ } else {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Unable to get device handler\n"));
+ }
+ goto errorExit;
+ }
+
+ IoReleaseDeviceHandler(deviceHandler);
+
+
+ //
+ // Call I/O mgr to get read data port addr
+ //
+
+ RtlZeroMemory(&ioResource, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
+ ioResource.ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResource.InterfaceType = Isa;
+ ioResource.AlternativeLists = 1;
+ ioResource.List[0].Version = 1;
+ ioResource.List[0].Revision = 1;
+ ioResource.List[0].Count = 1;
+ ioResource.List[0].Descriptors[0].Type = CmResourceTypePort;
+ ioResource.List[0].Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
+ ioResource.List[0].Descriptors[0].Flags = CM_RESOURCE_PORT_IO;
+ ioResource.List[0].Descriptors[0].u.Port.Length = 4;
+ ioResource.List[0].Descriptors[0].u.Port.Alignment = 4;
+ ioResource.List[0].Descriptors[0].u.Port.MinimumAddress.LowPart = MIN_READ_DATA_PORT;
+ ioResource.List[0].Descriptors[0].u.Port.MaximumAddress.LowPart = MAX_READ_DATA_PORT;
+ str = (PWSTR)ExAllocatePool(PagedPool, 512);
+ if (!str) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ goto errorExit;
+ }
+ swprintf(str, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s",
+ ServiceKeyName->Buffer);
+ RtlInitUnicodeString(&unicodeString, str);
+ status = IoAssignResources(&unicodeString,
+ NULL,
+ PipDriverObject,
+ PipBusExtension->BusHandler->DeviceObject,
+ &ioResource,
+ &cmResource);
+ ExFreePool(str);
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: IoAssignResources failed\n"));
+ goto errorExit;
+ }
+
+ PipBusExtension->ReadDataPort = (PUCHAR)(cmResource->List[0].PartialResourceList.
+ PartialDescriptors[0].u.Port.Start.LowPart + 3);
+ ExFreePool(cmResource);
+
+ //
+ // Perform initial bus check
+ //
+
+ PipCheckBus(busHandler);
+
+ return STATUS_SUCCESS;
+
+errorExit:
+
+ //
+ // BUGBUG We should unregister the bus handler and exit.
+ // HalUnregisterBusHandler is not supported.
+ //
+
+ return status;
+}
+
+NTSTATUS
+PiInstallBusHandler (
+ PBUS_HANDLER BusHandler
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked by Hal to initialize BUS_HANDLER structure and its
+ extension.
+
+Arguments:
+
+ BusHandler - spplies a pointer to Pnp Isa bus handler's BUS_HANDLER structure.
+
+Return Value:
+
+ A NTSTATUS code to indicate the result of the initialization.
+
+--*/
+
+{
+ WCHAR buffer[60];
+ UNICODE_STRING unicodeString;
+ PPI_DEVICE_EXTENSION deviceExtension;
+ NTSTATUS status;
+ PDEVICE_OBJECT deviceObject;
+
+ PAGED_CODE();
+
+ //
+ // Verify there's a parent handler
+ //
+
+ if (!BusHandler->ParentHandler) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Create device object for Pnp Isa bus extender.
+ //
+
+ swprintf (buffer, rgzPNPISADeviceName, BusHandler->BusNumber);
+ RtlInitUnicodeString (&unicodeString, buffer);
+
+ status = IoCreateDevice(
+ PipDriverObject,
+ sizeof(PI_DEVICE_EXTENSION),
+ &unicodeString,
+ FILE_DEVICE_BUS_EXTENDER,
+ 0,
+ FALSE,
+ &deviceObject
+ );
+
+ if (!NT_SUCCESS(status)) {
+ DebugPrint((DEBUG_MESSAGE,"PnpIsa: Failed to create device object for Pnp isa bus\n"));
+ return status;
+ }
+
+ // ===================================
+ // BUGBUG - need to find a solution
+ //
+
+ deviceObject->Flags &= ~0x80;
+
+ // ==================================
+ deviceExtension = (PPI_DEVICE_EXTENSION) deviceObject->DeviceExtension;
+ deviceExtension->BusHandler = BusHandler;
+
+ //
+ // Initialize bus handlers
+ //
+
+ BusHandler->DeviceObject = deviceObject;
+ BusHandler->GetBusData = (PGETSETBUSDATA) PiGetBusData;
+ BusHandler->SetBusData = (PGETSETBUSDATA) PiSetBusData;
+ BusHandler->QueryBusSlots = (PQUERY_BUS_SLOTS) PiQueryBusSlots;
+ BusHandler->DeviceControl = (PDEVICE_CONTROL) PiDeviceControl;
+ BusHandler->ReferenceDeviceHandler = (PREFERENCE_DEVICE_HANDLER) PiReferenceDeviceHandler;
+ BusHandler->GetDeviceData = (PGET_SET_DEVICE_DATA) PiGetDeviceData;
+ BusHandler->SetDeviceData = (PGET_SET_DEVICE_DATA) PiSetDeviceData;
+
+ //
+ // Intialize bus extension
+ //
+
+ PipBusExtension = (PPI_BUS_EXTENSION)BusHandler->BusData;
+ RtlZeroMemory(PipBusExtension, sizeof(PI_BUS_EXTENSION));
+ PipBusExtension->BusHandler = BusHandler;
+
+ InitializeListHead (&PipBusExtension->CheckBus);
+ InitializeListHead (&PipBusExtension->DeviceControl);
+
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/extender/pnpisa/i386/isolate.c b/private/ntos/nthals/extender/pnpisa/i386/isolate.c
new file mode 100644
index 000000000..53983ef71
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/isolate.c
@@ -0,0 +1,1574 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ isolate.c
+
+Abstract:
+
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-10-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "..\..\pnpbios\i386\pbios.h"
+#include "pnpisa.h"
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG Base,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ );
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ );
+
+//
+// Internal type definitions
+//
+
+typedef struct _MEMORY_DESC_{
+ ULONG Base;
+ ULONG Length;
+} MEMORY_DESC, *PMEMORY_DESC;
+
+typedef struct _IRQ_DESC_{
+ UCHAR Level;
+ ULONG Type;
+}IRQ_DESC, *PIRQ_DESC;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PipFindIrqInformation)
+#pragma alloc_text(PAGE,PipFindMemoryInformation)
+#pragma alloc_text(PAGE,PipFindIoPortInformation)
+#pragma alloc_text(PAGE,PipReadCardResourceData)
+#pragma alloc_text(PAGE,PipWriteDeviceBootResourceData)
+#pragma alloc_text(PAGE,PipLFSRInitiation)
+#pragma alloc_text(PAGE,PipIsolateCards)
+#endif
+
+BOOLEAN
+PipFindIrqInformation (
+ IN ULONG IrqLevel,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Irq descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. On input, the BiosRequirements points to current
+ logical id tag.
+
+Arguments:
+
+ IrqLevel - Supplies the irq level.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ ULONG increment;
+ USHORT irqMask;
+ PPNP_IRQ_DESCRIPTOR biosDesc;
+
+ //
+ // Skip current logical id tag
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the Irq.
+ //
+
+ irqMask = 1 << IrqLevel;
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
+ biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
+ if (biosDesc->IrqMask & irqMask) {
+ if ((tag & SMALL_TAG_MASK) == 2) {
+
+ //
+ // if no irq info is available, a value of zero is returned.
+ // (o is not a valid irq information.)
+ //
+
+ *Information = 0;
+ } else {
+ *Information = biosDesc->Information;
+ }
+ return TRUE;
+ }
+ }
+ increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+PipFindMemoryInformation (
+ IN ULONG BaseAddress,
+ IN ULONG Limit,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR NameTag,
+ OUT PUCHAR Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ memory descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag. Note, the memory range specified by Base
+ and Limit must be within a single Pnp ISA memory descriptor.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the memory range.
+
+ Limit - Supplies the upper limit of the memory range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ NameTag - Supplies a variable to receive the Tag of the memory descriptor which
+ describes the memory information.
+
+ Information - supplies a pointer to a UCHAR to receive the memory information
+ for the specified memory range.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+
+ //
+ // Skip current logical id tag.
+ //
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the memory range described by Base and Limit.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag) {
+ case TAG_MEMORY:
+ minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
+ length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
+ maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
+ + length - 1;
+ break;
+ case TAG_MEMORY32:
+ length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
+ maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
+ + length - 1;
+ break;
+ case TAG_MEMORY32_FIXED:
+ length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
+ minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
+ maxAddr = minAddr + length - 1;
+ break;
+ }
+
+ if (minAddr <= BaseAddress && maxAddr >= Limit) {
+ *Information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
+ *NameTag = tag;
+ found = TRUE;
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+BOOLEAN
+PipFindIoPortInformation (
+ IN ULONG BaseAddress,
+ IN PUCHAR BiosRequirements,
+ OUT PUCHAR Information,
+ OUT PUCHAR Alignment,
+ OUT PUCHAR RangeLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the Bios resource requirement lists for the corresponding
+ Io port descriptor information. The search stops when we encounter another logical
+ device id tag or the END tag.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the Io port range.
+
+ BiosRequirements - Supplies a pointer to the bios resource requirement lists. This
+ parameter must point to the logical device Id tag.
+
+ Information - supplies a pointer to a UCHAR to receive the port information/flags.
+
+ Alignment - supplies a pointer to a UCHAR to receive the port alignment
+ information.
+
+ RangeLength - supplies a pointer to a UCHAR to receive the port range length
+ information.
+
+Return Value:
+
+ TRUE - if memory information found. Else False.
+
+--*/
+{
+ UCHAR tag;
+ BOOLEAN found = FALSE;
+ ULONG minAddr, length, maxAddr, alignment;
+ USHORT increment;
+ PPNP_PORT_DESCRIPTOR portDesc;
+ PPNP_FIXED_PORT_DESCRIPTOR fixedPortDesc;
+
+ tag = *BiosRequirements;
+ ASSERT((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID);
+ BiosRequirements += (tag & SMALL_TAG_SIZE_MASK) + 1;
+
+ //
+ // Search the possible resource list to get the information
+ // for the io port range described by Base.
+ //
+
+ tag = *BiosRequirements;
+ while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID)) {
+ switch (tag & SMALL_TAG_MASK) {
+ case TAG_IO:
+ portDesc = (PPNP_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = portDesc->MinimumAddress;
+ maxAddr = portDesc->MaximumAddress;
+ if (minAddr <= BaseAddress && maxAddr >= BaseAddress) {
+ *Information = portDesc->Information;
+ *Alignment = portDesc->Alignment;
+ *RangeLength = portDesc->Length;
+ found = TRUE;
+ }
+ break;
+ case TAG_IO_FIXED:
+ fixedPortDesc = (PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements;
+ minAddr = fixedPortDesc->MinimumAddress;
+ if (BaseAddress == minAddr) {
+ *Information = 0; // 10 bit decode
+ *Alignment = 1;
+ *RangeLength = fixedPortDesc->Length;
+ found = TRUE;
+ }
+ break;
+ }
+
+ if (found) {
+ break;
+ }
+
+ //
+ // Advance to next tag
+ //
+
+ if (tag & LARGE_RESOURCE_TAG) {
+ increment = *(PUCHAR)(BiosRequirements + 1);
+ increment += 3; // length of large tag
+ } else {
+ increment = tag & SMALL_TAG_SIZE_MASK;
+ increment += 1; // length of small tag
+ }
+ BiosRequirements += increment;
+ tag = *BiosRequirements;
+ }
+ return found;
+}
+
+NTSTATUS
+PipReadCardResourceData (
+ IN ULONG Csn,
+ OUT PULONG NumberLogicalDevices,
+ IN PUCHAR *ResourceData,
+ OUT PULONG ResourceDataLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads resources data from a specified PnP ISA card. It is
+ caller's responsibility to release the memory. Before calling this routine,
+ the Pnp ISA card should be in sleep state (i.e. Initiation Key was sent.)
+ After exiting this routine, the card will be left in Config state.
+
+Arguments:
+
+ Csn - Specifies the CardSelectNumber to indicate which PNP ISA card.
+
+ NumberLogicalDevices - supplies a variable to receive the number of logical devices
+ associated with the Pnp Isa card.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ ResourceDataLength - Supplies a variable to receive the length of the ResourceData.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ PUCHAR buffer, p;
+ USHORT sizeToRead, size, limit, i;
+ UCHAR tag;
+ ULONG noDevices;
+
+ //
+ // Allocate memory to store the resource data.
+ // N.B. The buffer size should cover 99.999% of the machines.
+ //
+
+ sizeToRead = 4096;
+
+tryAgain:
+
+ noDevices = 0;
+ buffer = (PUCHAR)ExAllocatePoolWithTag(PagedPool, sizeToRead, 'iPnP');
+ if (!buffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Send card from sleep state to configuration state
+ // Note, by doing this the resource data includes 9 bytes Id.
+ //
+
+ PipWriteAddress (WAKE_CSN_PORT);
+ PipWriteData((UCHAR)Csn);
+
+ //
+ // Read the data until the buffer is full.
+ //
+
+ for (i = 0, p = buffer; i < sizeToRead; i++, p++) {
+ PipWriteAddress(CONFIG_DATA_STATUS_PORT);
+
+ //
+ // Waiting for data ready status bit
+ //
+
+ while ((PipReadData() & 1) != 1) {
+ }
+
+ //
+ // Read the data ...
+ //
+
+ PipWriteAddress(CONFIG_DATA_PORT);
+ *p = PipReadData();
+ }
+
+ //
+ // Next check if we got all the resource data and find out the real
+ // size of the resource data.
+ //
+
+ p = buffer + NUMBER_CARD_ID_BYTES;
+
+ //
+ // set search limit to be one byte less the (buffer size -
+ // size of ID bytes) to make sure the END TAG can be found before
+ // the last byte of the buffer. (This is because END tag contains
+ // one byte checksum.)
+ //
+
+ limit = sizeToRead - NUMBER_CARD_ID_BYTES - 1;
+ tag = *p;
+ while (tag != TAG_COMPLETE_END && limit > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // move to next descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ noDevices++;
+ }
+ } else {
+ size = *(PUSHORT)(p + 1);
+ size += 3; // length of large tag
+ }
+
+ p += size;
+ limit -= size;
+ tag = *p;
+ }
+ if (tag == TAG_COMPLETE_END) {
+
+ //
+ // Determine the real size of the buffer required and
+ // resize the buffer.
+ //
+
+ size = p - buffer + 1 + 1; // add 1 for end tag checksum byte
+ p = (PUCHAR)ExAllocatePoolWithTag(PagedPool, size, 'iPnP');
+ if (p) {
+ RtlMoveMemory(p, buffer, size);
+ ExFreePool(buffer);
+ } else {
+
+ //
+ // Fail to resize the buffer. Simply leave it alone.
+ //
+
+ p = buffer;
+ }
+
+ //
+ // Should we leave card in config state???
+ //
+
+ *ResourceData = p;
+ *NumberLogicalDevices = noDevices;
+ *ResourceDataLength = size;
+ return STATUS_SUCCESS;
+ } else {
+
+ //
+ // We did not find the resource END TAG. This means we did not
+ // get all the resource data on previous read. Try to expand the
+ // data buffer and read again.
+ //
+#if DBG
+ DbgBreakPoint();
+#endif
+ ExFreePool(buffer);
+ sizeToRead <<= 1; // double the buffer
+
+ //
+ // If we can find the END tag with 32K byte, assume the resource
+ // requirement list is bad.
+ //
+
+ if (sizeToRead > 0x80000) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ goto tryAgain;
+ }
+}
+
+NTSTATUS
+PipReadDeviceBootResourceData (
+ IN ULONG BusNumber,
+ IN PUCHAR BiosRequirements,
+ OUT PCM_RESOURCE_LIST *ResourceData,
+ OUT PULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads boot resource data from an enabled logical device of a PNP ISA card.
+ Caller must put the card into configuration state and select the logical device before
+ calling this function. It is caller's responsibility to release the memory. ( The boot
+ resource data is the resources that a card assigned during boot.)
+
+Arguments:
+
+ BusNumber - specifies the bus number of the device whose resource data to be read.
+
+ BiosRequirements - Supplies a pointer to the resource requirement list for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a variable to receive the pointer to the resource data.
+
+ Length - Supplies a variable to recieve the length of the resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+
+ UCHAR c, junk1, junk2;
+ PUCHAR base;
+ ULONG l, resourceCount;
+ BOOLEAN limit;
+ LONG i, j, noMemoryDesc = 0, noIoDesc = 0, noDmaDesc =0, noIrqDesc = 0;
+ MEMORY_DESC memoryDesc[NUMBER_MEMORY_DESCRIPTORS + NUMBER_32_MEMORY_DESCRIPTORS];
+ IRQ_DESC irqDesc[NUMBER_IRQ_DESCRIPTORS];
+ UCHAR dmaDesc[NUMBER_DMA_DESCRIPTORS];
+ USHORT ioDesc[NUMBER_IO_DESCRIPTORS];
+ PCM_RESOURCE_LIST cmResource;
+ PCM_PARTIAL_RESOURCE_LIST partialResList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
+
+#if DBG
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DbgPrint("PnpIsa-ReadDeviceBootResourceData:The logical device has not been activated\n");
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Read memory configuration
+ //
+
+ base = (PUCHAR)ADDRESS_MEMORY_BASE;
+ for (i = 0; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+
+ //
+ // Read memory base address
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8; // l = memory base address
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_HI);
+ c = PipReadData();
+ l = c;
+ l <<= 8;
+ PipWriteAddress(base + ADDRESS_MEMORY_UPPER_LO);
+ c = PipReadData();
+ l |= c;
+ l <<= 8;
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ noMemoryDesc++;
+ base += ADDRESS_MEMORY_INCR;
+ }
+
+ //
+ // Read memory 32 configuration
+ //
+
+ for (i = 0; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+
+ base = ADDRESS_32_MEMORY_BASE(i);
+
+ //
+ // Read memory base address
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_B3; j <= ADDRESS_32_MEMORY_B0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+ if (l == 0) {
+ break;
+ }
+
+ memoryDesc[noMemoryDesc].Base = l;
+
+ //
+ // Read memory control byte
+ //
+
+ PipWriteAddress(base + ADDRESS_32_MEMORY_CTL);
+ c= PipReadData();
+ limit = c & 1;
+
+ //
+ // Read memory upper limit address or range length
+ //
+
+ l = 0;
+ for (j = ADDRESS_32_MEMORY_E3; j <= ADDRESS_32_MEMORY_E0; j++) {
+ PipWriteAddress(base + j);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ }
+
+ if (limit == ADDRESS_MEMORY_CTL_LIMIT) {
+ l = l - memoryDesc[noMemoryDesc].Base;
+ }
+ memoryDesc[noMemoryDesc].Length = l;
+ noMemoryDesc++;
+ }
+
+ //
+ // Read Io Port Configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IO_BASE;
+ for (i = 0; i < NUMBER_IO_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IO_BASE_HI);
+ c = PipReadData();
+ l = c;
+ PipWriteAddress(base + ADDRESS_IO_BASE_LO);
+ c = PipReadData();
+ l <<= 8;
+ l |= c;
+ if (l == 0) {
+ break;
+ }
+ ioDesc[noIoDesc++] = (USHORT)l;
+ base += ADDRESS_IO_INCR;
+ }
+
+ //
+ // Read Interrupt configuration
+ //
+
+ base = (PUCHAR)ADDRESS_IRQ_BASE;
+ for (i = 0; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_IRQ_VALUE);
+ c = PipReadData();
+ if (c == 0) {
+ break;
+ }
+ irqDesc[noIrqDesc].Level = c;
+ PipWriteAddress(base + ADDRESS_IRQ_TYPE);
+ c = PipReadData();
+ irqDesc[noIrqDesc++].Type = c;
+ base += ADDRESS_IRQ_INCR;
+ }
+
+ //
+ // Read DMA configuration
+ //
+
+ base = (PUCHAR)ADDRESS_DMA_BASE;
+ for (i = 0; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(base + ADDRESS_DMA_VALUE);
+ c = PipReadData();
+ if (c == 4) {
+ break;
+ }
+ dmaDesc[noDmaDesc++] = c;
+ base += ADDRESS_IRQ_INCR;
+ }
+
+ //
+ // Construct CM_RESOURCE_LIST structure based on the resource data
+ // we collect so far.
+ //
+
+ resourceCount = noMemoryDesc + noIoDesc + noDmaDesc + noIrqDesc;
+
+ //
+ // if empty bios resources, simply return.
+ //
+
+ if (resourceCount == 0) {
+ *ResourceData = NULL;
+ *Length = 0;
+ return STATUS_SUCCESS;
+ }
+
+ l = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
+ ( resourceCount - 1);
+ cmResource = ExAllocatePoolWithTag(PagedPool, l, 'iPnP');
+ if (!cmResource) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(cmResource, l);
+ *Length = l; // Set returned resource data length
+ cmResource->Count = 1;
+ cmResource->List[0].InterfaceType = Isa;
+ cmResource->List[0].BusNumber = BusNumber;
+ partialResList = (PCM_PARTIAL_RESOURCE_LIST)&cmResource->List[0].PartialResourceList;
+ partialResList->Version = 0;
+ partialResList->Revision = 0;
+ partialResList->Count = resourceCount;
+ partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
+
+ //
+ // Set up all the CM memory descriptors
+ //
+
+ for (i = 0; i < noMemoryDesc; i++) {
+ partialDesc->Type = CmResourceTypeMemory;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->u.Memory.Length = memoryDesc[i].Length;
+ partialDesc->u.Memory.Start.HighPart = 0;
+ partialDesc->u.Memory.Start.LowPart = memoryDesc[i].Base;
+
+ //
+ // Need to consult configuration data for the Flags
+ //
+
+ l = memoryDesc[i].Base + memoryDesc[i].Length - 1;
+ if (PipFindMemoryInformation (memoryDesc[i].Base, l, BiosRequirements, &junk1, &c)) {
+ if (c & PNP_MEMORY_WRITE_STATUS_MASK) {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+ partialDesc++;
+ } else {
+#if DBG
+ DbgPrint("PnpIsa-ReadDeviceBootResourceData:No matched memory information in config data\n");
+ DbgBreakPoint();
+#endif
+ }
+ }
+
+ //
+ // Set up all the CM io/port descriptors
+ //
+
+ for (i = 0; i < noIoDesc; i++) {
+ partialDesc->Type = CmResourceTypePort;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = CM_RESOURCE_PORT_IO;
+ partialDesc->u.Port.Start.LowPart = ioDesc[i];
+
+ //
+ // Need to consult configuration data for the Port length
+ //
+
+ if (PipFindIoPortInformation (ioDesc[i], BiosRequirements, &junk1, &junk2, &c)) {
+ partialDesc->u.Port.Length = c;
+ partialDesc++;
+ } else {
+#if DBG
+ DbgPrint("PnpIsa-ReadDeviceBootResourceData:No matched port length in config data\n");
+ DbgBreakPoint();
+#endif
+ }
+ }
+
+ //
+ // Set up all the CM DMA descriptors
+ //
+
+ for (i = 0; i < noDmaDesc; i++) {
+ partialDesc->Type = CmResourceTypeDma;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ partialDesc->Flags = 0; // no flags for DMA descriptor
+ partialDesc->u.Dma.Channel = (ULONG) dmaDesc[i];
+ partialDesc->u.Dma.Port = 0;
+ partialDesc->u.Dma.Reserved1 = 0;
+ partialDesc++;
+ }
+
+ //
+ // Set up all the CM interrupt descriptors
+ //
+
+ for (i = 0; i < noIrqDesc; i++) {
+ partialDesc->Type = CmResourceTypeInterrupt;
+ partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (irqDesc[i].Type & 1) {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ } else {
+ partialDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ }
+ partialDesc->u.Interrupt.Vector =
+ partialDesc->u.Interrupt.Level = irqDesc[i].Level;
+ partialDesc->u.Interrupt.Affinity = (ULONG)-1;
+ partialDesc++;
+ }
+
+ *ResourceData = cmResource;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+PipWriteDeviceBootResourceData (
+ IN PUCHAR BiosRequirements,
+ IN PCM_RESOURCE_LIST CmResources
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes boot resource data to an enabled logical device of
+ a Pnp ISA card. Caller must put the card into configuration state and select
+ the logical device before calling this function.
+
+Arguments:
+
+ BiosRequirements - Supplies a pointer to the possible resources for the logical
+ device. This parameter must point to the logical device Id tag.
+
+ ResourceData - Supplies a pointer to the cm resource data.
+
+Return Value:
+
+ NT STATUS code.
+
+--*/
+{
+ UCHAR c, information;
+ ULONG count, i, j, pass, base, limit;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
+ ULONG noIrq =0, noIo = 0, noDma = 0, noMemory = 0, no32Memory = 0;
+ PUCHAR memoryBase, irqBase, dmaBase, ioBase, tmp;
+ ULONG memory32Base;
+
+#if DBG
+ PipWriteAddress(ACTIVATE_PORT);
+ if (!(PipReadData() & 1)) {
+ DbgPrint("PnpIsa-WriteDeviceBootResourceData:The logical device has not been activated\n");
+ }
+#endif // DBG
+
+ //
+ // First make sure the specified BiosRequirements is valid and at the right tag.
+ //
+
+ if ((*BiosRequirements & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ count = CmResources->List[0].PartialResourceList.Count;
+ memoryBase = (PUCHAR)ADDRESS_MEMORY_BASE;
+ memory32Base = 0;
+ ioBase = (PUCHAR)ADDRESS_IO_BASE;
+ irqBase = (PUCHAR)ADDRESS_IRQ_BASE;
+ dmaBase = (PUCHAR)ADDRESS_DMA_BASE;
+ for (pass = 1; pass <= 2; pass++) {
+
+ //
+ // First pass we make sure the resources to be set is acceptable.
+ // Second pass we actually write the resources to the logical device's
+ // configuration space.
+ //
+
+ cmDesc = CmResources->List[0].PartialResourceList.PartialDescriptors;
+ for (i = 0; i < count; i++) {
+ switch (cmDesc->Type) {
+ case CmResourceTypePort:
+ if (pass == 1) {
+ noIo++;
+ if (noIo > NUMBER_IO_DESCRIPTORS ||
+ cmDesc->u.Port.Start.HighPart != 0 ||
+ cmDesc->u.Port.Start.LowPart & 0xffff0000 ||
+ cmDesc->u.Port.Length & 0xffffff00) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Io port base address to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Port.Start.LowPart;
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_LO);
+ PipWriteData(c);
+ c = (UCHAR)(cmDesc->u.Port.Start.LowPart >> 8);
+ PipWriteAddress(ioBase + ADDRESS_IO_BASE_HI);
+ PipWriteData(c);
+ ioBase += ADDRESS_IO_INCR;
+ }
+ break;
+ case CmResourceTypeInterrupt:
+ if (pass == 1) {
+ noIrq++;
+ if (noIrq > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Interrupt.Level & 0xfffffff0)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // See if we can get the interrupt information from possible resource
+ // data. We need it to set the configuration register.
+ //
+
+ if (!PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Irq to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Interrupt.Level;
+ PipWriteAddress(irqBase + ADDRESS_IRQ_VALUE);
+ PipWriteData(c);
+ PipFindIrqInformation(cmDesc->u.Interrupt.Level, BiosRequirements, &information);
+ if (information != 0) {
+ switch (information & 0xf) {
+ case 1: // High true edge sensitive
+ c = 2;
+ break;
+ case 2: // Low true edge sensitive
+ c = 0;
+ break;
+ case 4: // High true level sensitive
+ c = 3;
+ break;
+ case 8: // Low true level sensitive
+ c = 1;
+ break;
+ }
+ PipWriteAddress(irqBase + ADDRESS_IRQ_TYPE);
+ PipWriteData(c);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ break;
+ case CmResourceTypeDma:
+ if (pass == 1) {
+ noDma++;
+ if (noDma > NUMBER_IRQ_DESCRIPTORS ||
+ (cmDesc->u.Dma.Channel & 0xfffffff8)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ } else {
+
+ //
+ // Set the Dma channel to logical device configuration space
+ //
+
+ c = (UCHAR)cmDesc->u.Dma.Channel;
+ PipWriteAddress(dmaBase + ADDRESS_DMA_VALUE);
+ PipWriteData(c);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ break;
+ case CmResourceTypeMemory:
+ if (pass == 1) {
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ if (!PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information)) {
+ return STATUS_INVALID_PARAMETER;
+ } else {
+ switch (c) {
+ case TAG_MEMORY:
+ noMemory++;
+
+ //
+ // Make sure the lower 8 bits of the base address are zero.
+ //
+
+ if (noMemory > NUMBER_MEMORY_DESCRIPTORS ||
+ base & 0xff) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ break;
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ no32Memory++;
+ if (no32Memory > NUMBER_32_MEMORY_DESCRIPTORS) {
+ return STATUS_INVALID_PARAMETER;
+ }
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+ } else {
+
+ //
+ // Find information in BiosRequirements to help determine how to write
+ // the memory configuration space.
+ //
+
+ base = cmDesc->u.Memory.Start.LowPart;
+ limit = base + cmDesc->u.Memory.Length - 1;
+ PipFindMemoryInformation(base, limit, BiosRequirements, &c, &information);
+ switch (c) {
+ case TAG_MEMORY:
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_LO);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_HI);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_CTL);
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT; // assume 16 bit memory
+ if (information & 0x18 == 0) { // 8 bit memory only
+ c = 0 + ADDRESS_MEMORY_CTL_LIMIT;
+ }
+ PipWriteData(c);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_LO);
+ PipWriteData((UCHAR)limit);
+ limit >>= 8;
+ PipWriteAddress(memoryBase + ADDRESS_MEMORY_UPPER_HI);
+ PipWriteData((UCHAR)limit);
+ memoryBase += ADDRESS_MEMORY_INCR;
+ break;
+ case TAG_MEMORY32:
+ case TAG_MEMORY32_FIXED:
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B0);
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B1);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B2);
+ base >>= 8;
+ PipWriteData(base);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_B3);
+ base >>= 8;
+ PipWriteData(base);
+ switch (information & 0x18) {
+ case 0: // 8 bit only
+ c = ADDRESS_MEMORY_CTL_LIMIT;
+ case 8: // 16 bit only
+ case 0x10: // 8 and 16 bit supported
+ c = 2 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ case 0x18: // 32 bit only
+ c = 6 + ADDRESS_MEMORY_CTL_LIMIT;
+ break;
+ }
+ PipWriteAddress(ADDRESS_32_MEMORY_CTL);
+ PipWriteData(c);
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E0);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E1);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E2);
+ PipWriteData(limit);
+ limit >>= 8;
+ PipWriteAddress(tmp + ADDRESS_32_MEMORY_E3);
+ PipWriteData(limit);
+ memory32Base++;
+ break;
+ }
+ }
+ break;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+ cmDesc++;
+ }
+ }
+
+ //
+ // Finally, mark all the unused descriptors as disabled.
+ //
+
+ for (i = noMemory; i < NUMBER_MEMORY_DESCRIPTORS; i++) {
+ for (j = 0; j < 5; j++) {
+ PipWriteAddress(memoryBase + j);
+ PipWriteData(0);
+ }
+ memoryBase += ADDRESS_MEMORY_INCR;
+ }
+ for (i = no32Memory; i < NUMBER_32_MEMORY_DESCRIPTORS; i++) {
+ tmp = ADDRESS_32_MEMORY_BASE(memory32Base);
+ for (j = 0; j < 9; j++) {
+ PipWriteAddress(tmp + j);
+ PipWriteData(0);
+ }
+ memory32Base++;
+ }
+ for (i = noIo; i < NUMBER_IO_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(ioBase + j);
+ PipWriteData(0);
+ }
+ ioBase += ADDRESS_IO_INCR;
+ }
+ for (i = noIrq; i < NUMBER_IRQ_DESCRIPTORS; i++) {
+ for (j = 0; j < 2; j++) {
+ PipWriteAddress(irqBase + j);
+ PipWriteData(0);
+ }
+ irqBase += ADDRESS_IRQ_INCR;
+ }
+ for (i = noDma; i < NUMBER_DMA_DESCRIPTORS; i++) {
+ PipWriteAddress(dmaBase);
+ PipWriteData(4);
+ dmaBase += ADDRESS_DMA_INCR;
+ }
+ return STATUS_SUCCESS;
+}
+
+VOID
+PipLFSRInitiation (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insures the LFSR (linear feedback shift register) is in its
+ initial state and then performs 32 writes to the ADDRESS port to initiation
+ LFSR function.
+
+ Pnp software sends the initiation key to all the Pnp ISA cards to place them
+ into configuration mode. The software then ready to perform isolation
+ protocol.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR seed, bit7;
+ ULONG i;
+
+ //
+ // First perform two writes of value zero to insure the LFSR is in the
+ // initial state.
+ //
+
+ PipWriteAddress (0);
+ PipWriteAddress (0);
+
+ //
+ // Perform the initiation key.
+ //
+
+ seed = LFSR_SEED; // initial value of 0x6a
+ for (i = 0; i < 32; i++) {
+ PipWriteAddress (seed);
+ bit7=(((seed & 2) >> 1) ^ (seed & 1)) << 7;
+ seed =(seed >> 1) | bit7;
+ }
+}
+
+VOID
+PipIsolateCards (
+ OUT PULONG NumberCSNs,
+ IN OUT PUCHAR *ReadDataPort
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs PnP ISA cards isolation sequence.
+
+Arguments:
+
+ NumberCSNs - supplies the addr of a variable to receive the number of
+ Pnp Isa cards isolated.
+
+ ReadDataPort - Supplies the address of a variable to supply ReadData port
+ address. If NULL is supplied, this function returns detected ReadData
+ port to this variable.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT j, i;
+ UCHAR cardId[NUMBER_CARD_ID_BYTES];
+ UCHAR bit, bit7, checksum, byte1, byte2;
+ ULONG csn = 0;
+
+ //
+ // First send Initiation Key to all the PNP ISA cards to put them into
+ // configuration mode.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Reset all Pnp ISA cards' CSN to 0 and return to wait-for-key state
+ //
+
+ PipWriteAddress (CONFIG_CONTROL_PORT);
+ PipWriteData (CONTROL_WAIT_FOR_KEY | CONTROL_RESET_CSN);
+
+ //
+ // Delay 2 msec for cards to load initial configuration state.
+ //
+
+ KeStallExecutionProcessor(20000); // delay 2 msec
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Starting Pnp Isa card isolation process.
+ // Try Read_Data_port from 200 to 3ff if ReadData port addr is not supplied.
+ //
+
+ for (i = MIN_READ_DATA_PORT; i < MAX_READ_DATA_PORT; i += 4) {
+
+ if ((i & 0xf) == 0) {
+
+ //
+ // Some cards (e.g. 3COM elnkiii) do not response to 0xyy3 addr.
+ //
+
+ continue;
+ }
+ if (*ReadDataPort) {
+ PipReadDataPort = *ReadDataPort;
+ } else {
+ PipReadDataPort = (PUCHAR)(i + 3);;
+ }
+
+ //
+ // Send WAKE[CSN=0] to force all cards without CSN into isolation
+ // state to set READ DATA PORT.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ //
+ // Set read data port to current testing value.
+ //
+
+ PipWriteAddress(SET_READ_DATA_PORT);
+ PipWriteData((UCHAR)((ULONG)PipReadDataPort >> 2));
+
+ //
+ // Isolate one PnP ISA card until fail
+ //
+
+ while (TRUE) {
+
+ //
+ // Read serial isolation port to cause PnP cards in the isolation
+ // state to compare one bit of the boards ID.
+ //
+
+ PipWriteAddress(SERIAL_ISOLATION_PORT);
+
+ //
+ // We need to delay 1msec prior to starting the first pair of isolation
+ // reads and must wait 250usec between each subsequent pair of isolation
+ // reads. This delay gives the ISA cards time to access information from
+ // possible very slow storage device.
+ //
+
+ KeStallExecutionProcessor(10000); // delay 1 msec
+
+ RtlZeroMemory(cardId, NUMBER_CARD_ID_BYTES);
+ checksum = LFSR_SEED;
+ for (j = 0; j < NUMBER_CARD_ID_BITS; j++) {
+
+ //
+ // Read card id bit by bit
+ //
+
+ byte1 = READ_PORT_UCHAR (PipReadDataPort);
+ byte2 = READ_PORT_UCHAR (PipReadDataPort);
+ bit = (byte1 == ISOLATION_TEST_BYTE_1) && (byte2 == ISOLATION_TEST_BYTE_2);
+ cardId[j / 8] |= bit << (j % 8);
+ if (j < CHECKSUMED_BITS) {
+
+ //
+ // Calculate checksum
+ //
+
+ bit7 = (((checksum & 2) >> 1) ^ (checksum & 1) ^ (bit)) << 7;
+ checksum = (checksum >> 1) | bit7;
+ }
+ KeStallExecutionProcessor(2500); // delay 250 usec
+ }
+
+ //
+ // Verify the card id we read is legitimate
+ // First make sure checksum is valid. Note zero checksum is considered valid.
+ //
+
+ if (cardId[8] == 0 || checksum == cardId[8]) {
+
+ //
+ // Next make sure cardId is not zero
+ //
+
+ byte1 = 0;
+ for (j = 0; j < NUMBER_CARD_ID_BYTES; j++) {
+ byte1 |= cardId[j];
+ }
+ if (byte1 != 0) {
+
+ //
+ // We found a valid Pnp Isa card, assign it a CSN number
+ //
+
+ PipWriteAddress(SET_CSN_PORT);
+
+ PipWriteData(++csn);
+
+ //
+ // Do Wake[CSN] command to put the newly isolated card to
+ // sleep state and other un-isolated cards to isolation
+ // state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(0);
+
+ continue; // ... to isolate more cards ...
+ }
+ }
+ break; // could not isolate more cards ...
+ }
+
+ //
+ // If we isolated at least one card, it means the read data port we use
+ // must be good and we can stop the isolation process. Otherwise try another
+ // read data port address.
+ //
+
+ if (csn != 0 || *ReadDataPort) {
+ if (*ReadDataPort == NULL) {
+ *ReadDataPort = PipReadDataPort;
+ }
+ break;
+ }
+ }
+
+ //
+ // Finaly put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+ *NumberCSNs = csn;
+}
+
+ULONG
+PipFindNextLogicalDeviceTag (
+ IN OUT PUCHAR *CardData,
+ IN OUT LONG *Limit
+ )
+
+/*++
+
+Routine Description:
+
+ This function searches the Pnp Isa card data for the Next logical
+ device tag encountered. The input *CardData should point to an logical device id tag,
+ which is the current logical device tag. If the *CardData does not point to a logical
+ device id tag, it will be moved to next tag.
+
+Arguments:
+
+ CardData - a variable to supply a pointer to the pnp Isa resource descriptors and to
+ receive next logical device tag pointer.
+
+ Limit - a variable to supply the maximum length of the search and to receive the new
+ lemit after the search.
+
+Return Value:
+
+ Length of the data between current and next logical device tags, ie the data length
+ of the current logical device.
+ In case there is no 'next' logical device tag, the returned *CardData = NULL,
+ *Limit = zero and the data length of current logical tag is returned as function
+ returned value.
+
+--*/
+{
+ UCHAR tag;
+ USHORT size;
+ LONG l;
+ ULONG retLength;
+ PUCHAR p;
+ BOOLEAN atIdTag = FALSE;;
+
+ p = *CardData;
+ l = *Limit;
+ tag = *p;
+ retLength = 0;
+ while (tag != TAG_COMPLETE_END && l > 0) {
+
+ //
+ // Determine the size of the BIOS resource descriptor
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(p + 1);
+ size += 3; // length of large tag
+ }
+
+ p += size;
+ retLength += size;
+ l -= size;
+ tag = *p;
+ if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
+ *CardData = p;
+ *Limit = l;
+ return retLength;
+ }
+ }
+ *CardData = NULL;
+ *Limit = 0;
+ if (tag == TAG_COMPLETE_END) {
+ return (retLength + 2); // add 2 for the length of end tag descriptor
+ } else {
+ return 0;
+ }
+}
+
+VOID
+PipSelectLogicalDevice (
+ IN USHORT Csn,
+ IN USHORT LogicalDeviceNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function selects the logical logical device in the specified device.
+
+Arguments:
+
+ Csn - Supplies a CardSelectNumber to select the card.
+
+ LogicalDeviceNumber - supplies a logical device number to select the logical device.
+
+Return Value:
+
+ None
+--*/
+{
+ UCHAR tmp;
+
+ //
+ // Put cards into configuration mode to ready isolation process.
+ //
+
+ PipLFSRInitiation ();
+
+ //
+ // Send WAKE[CSN] to force the card into config state.
+ //
+
+ PipWriteAddress(WAKE_CSN_PORT);
+ PipWriteData(Csn);
+
+ //
+ // Select the logical device, disable its io range check and
+ // enable the device.
+ //
+
+ PipWriteAddress(LOGICAL_DEVICE_PORT);
+ PipWriteData(LogicalDeviceNumber);
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ tmp = PipReadData();
+ tmp &= ~2;
+ PipWriteAddress(IO_RANGE_CHECK_PORT);
+ PipWriteData(tmp);
+ PipWriteAddress(ACTIVATE_PORT);
+ PipWriteData(1);
+}
diff --git a/private/ntos/nthals/extender/pnpisa/i386/misc.c b/private/ntos/nthals/extender/pnpisa/i386/misc.c
new file mode 100644
index 000000000..0ba14e5ec
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/misc.c
@@ -0,0 +1,626 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ misc.c
+
+Abstract:
+
+ This file contains pnp isa bus extender support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) 27-Jusly-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "busp.h"
+#include "pnpisa.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,PiCreateClose)
+#pragma alloc_text(PAGE,PiUnload)
+#pragma alloc_text(PAGE,PipGetRegistryValue)
+#pragma alloc_text(PAGE,PipDecompressEisaId)
+#endif
+
+
+NTSTATUS
+PiCreateClose (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles open and close requests such that our device objects
+ can be opened. All it does it to complete the Irp with success.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer to the device object to be opened or closed.
+
+ Irp - supplies a pointer to I/O request packet.
+
+Return Value:
+
+ Always returns STATUS_SUCCESS, since this is a null operation.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( DeviceObject );
+
+ PAGED_CODE();
+
+ //
+ // Null operation. Do not give an I/O boost since no I/O was
+ // actually done. IoStatus.Information should be
+ // FILE_OPENED for an open; it's undefined for a close.
+ //
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = FILE_OPENED;
+
+ IoCompleteRequest( Irp, 0);
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+PiUnload(
+ IN PDRIVER_OBJECT DriverObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine cleans up all of the memory associated with
+ any of the devices belonging to the driver.
+
+Arguments:
+
+ DriverObject - Supplies a pointer to the driver object controling
+ all of the devices.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PVOID lockPtr;
+
+ //
+ // Lock the pageable code section
+ //
+
+ lockPtr = MmLockPagableCodeSection(PiUnload);
+
+ ExAcquireFastMutex (&PipMutex);
+
+ ObDereferenceObject(PipBusExtension->BusHandler->DeviceObject);
+
+ //
+ // Delete all the device info structures and card info structures
+ //
+
+ PipInvalidateCards(PipBusExtension);
+ PipDeleteCards(PipBusExtension);
+
+ //
+ // Finally remove the bus handler reference.
+ //
+
+ HalDereferenceBusHandler (PipBusExtension->BusHandler);
+
+ ExReleaseFastMutex (&PipMutex);
+
+ //
+ // Unlock pageable code section
+ //
+
+ MmUnlockPagableImageSection(lockPtr);
+}
+
+NTSTATUS
+PiReconfigureResources (
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN DRIVER_RECONFIGURE_OPERATION Operation,
+ IN PCM_RESOURCE_LIST CmResources
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reconfigures Read Data Port address.
+
+Arguments:
+
+ DriverObject - Supplies a pointer to the driver object controling
+ all of the devices.
+
+ DeviceObject - Supplies a pointer to the device object whoes resources
+ are going to be reconfigured.
+
+ Operation - the operation of the reconfiguration request.
+
+ CmResources - supplies a pointer to the cm resource list.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+
+{
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG port, count, i;
+
+ UNREFERENCED_PARAMETER( DriverObject );
+ UNREFERENCED_PARAMETER( DeviceObject );
+
+ switch (Operation) {
+ case ReconfigureResources:
+ ExAcquireFastMutex(&PipPortMutex);
+
+ //
+ // retrieve the new read data port address
+ //
+
+ ASSERT(CmResources->Count == 1);
+ partialDesc = &CmResources->List[0].PartialResourceList;
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ switch (desc->Type) {
+ case CmResourceTypePort:
+ port = desc->u.Port.Start.LowPart;
+ if (desc->u.Port.Length != 4 || port & 0x3) {
+ return STATUS_UNSUCCESSFUL;
+ } else {
+ port += 3;
+ }
+ break;
+
+ case CmResourceTypeMemory:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeDma:
+ break;
+ }
+ desc++;
+ }
+
+ //
+ // Set read data port to the new setting.
+ //
+
+ PipBusExtension->ReadDataPort = (PUCHAR)port;
+ PipReadDataPort = (PUCHAR)port;
+
+ PipWriteAddress(SET_READ_DATA_PORT);
+ PipWriteData((UCHAR)((ULONG)PipReadDataPort >> 2));
+
+ ExReleaseFastMutex(&PipPortMutex);
+ break;
+
+ case QueryReconfigureResources:
+ case CancelReconfigureQuery:
+ case QueryHardwareProfileChange:
+ case HardwareProfileChanged:
+ default:
+ break;
+ }
+ return STATUS_SUCCESS;
+}
+
+VOID
+PipDecompressEisaId(
+ IN ULONG CompressedId,
+ IN PUCHAR EisaId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decompressed compressed Eisa Id and returns the Id to caller
+ specified character buffer.
+
+Arguments:
+
+ CompressedId - supplies the compressed Eisa Id.
+
+ EisaId - supplies a 8-char buffer to receive the decompressed Eisa Id.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT c1, c2;
+ LONG i;
+
+ PAGED_CODE();
+
+ CompressedId &= 0xffffff7f; // remove the reserved bit (bit 7 of byte 0)
+ c1 = c2 = (USHORT)CompressedId;
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ for (i = 2; i >= 0; i--) {
+ *(EisaId + i) = (UCHAR)(c1 & 0x1f) + 0x40;
+ c1 >>= 5;
+ }
+ EisaId += 3;
+ c1 = c2 = (USHORT)(CompressedId >> 16);
+ c1 = (c1 & 0xff) << 8;
+ c2 = (c2 & 0xff00) >> 8;
+ c1 |= c2;
+ sprintf (EisaId, "%04x", c1);
+}
+
+NTSTATUS
+PipGetRegistryValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName,
+ OUT PKEY_VALUE_FULL_INFORMATION *Information
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to retrieve the data for a registry key's value.
+ This is done by querying the value of the key with a zero-length buffer
+ to determine the size of the value, and then allocating a buffer and
+ actually querying the value into the buffer.
+
+ It is the responsibility of the caller to free the buffer.
+
+Arguments:
+
+ KeyHandle - Supplies the key handle whose value is to be queried
+
+ ValueName - Supplies the null-terminated Unicode name of the value.
+
+ Information - Returns a pointer to the allocated data buffer.
+
+Return Value:
+
+ The function value is the final status of the query operation.
+
+--*/
+
+{
+ UNICODE_STRING unicodeString;
+ NTSTATUS status;
+ PKEY_VALUE_FULL_INFORMATION infoBuffer;
+ ULONG keyValueLength;
+
+ PAGED_CODE();
+
+ RtlInitUnicodeString( &unicodeString, ValueName );
+
+ //
+ // Figure out how big the data value is so that a buffer of the
+ // appropriate size can be allocated.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ (PVOID) NULL,
+ 0,
+ &keyValueLength );
+ if (status != STATUS_BUFFER_OVERFLOW &&
+ status != STATUS_BUFFER_TOO_SMALL) {
+ return status;
+ }
+
+ //
+ // Allocate a buffer large enough to contain the entire key data value.
+ //
+
+ infoBuffer = ExAllocatePool( NonPagedPool, keyValueLength );
+ if (!infoBuffer) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Query the data for the key value.
+ //
+
+ status = ZwQueryValueKey( KeyHandle,
+ &unicodeString,
+ KeyValueFullInformation,
+ infoBuffer,
+ keyValueLength,
+ &keyValueLength );
+ if (!NT_SUCCESS( status )) {
+ ExFreePool( infoBuffer );
+ return status;
+ }
+
+ //
+ // Everything worked, so simply return the address of the allocated
+ // buffer to the caller, who is now responsible for freeing it.
+ //
+
+ *Information = infoBuffer;
+ return STATUS_SUCCESS;
+}
+#if DBG
+
+VOID
+PipDebugPrint (
+ ULONG Level,
+ PCCHAR DebugMessage,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This routine displays debugging message or causes a break.
+
+Arguments:
+
+ Level - supplies debugging levelcode. DEBUG_MESSAGE - displays message only.
+ DEBUG_BREAK - displays message and break.
+
+ DebugMessage - supplies a pointer to the debugging message.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Buffer[256];
+ va_list ap;
+
+ va_start(ap, DebugMessage);
+
+ vsprintf(Buffer, DebugMessage, ap);
+ DbgPrint(Buffer);
+ if (Level == DEBUG_BREAK) {
+ DbgBreakPoint();
+ }
+
+ va_end(ap);
+}
+
+VOID
+PipDumpIoResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PIO_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR c = ' ';
+
+ if (Desc->Option == IO_RESOURCE_ALTERNATIVE) {
+ c = 'A';
+ } else if (Desc->Option == IO_RESOURCE_PREFERRED) {
+ c = 'P';
+ }
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Port.MinimumAddress.HighPart, Desc->u.Port.MinimumAddress.LowPart,
+ Desc->u.Port.MaximumAddress.HighPart, Desc->u.Port.MaximumAddress.LowPart,
+ Desc->u.Port.Alignment,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM %c Min: %x:%08x, Max: %x:%08x, Algn: %x, Len %x\n",
+ Indent, c,
+ Desc->u.Memory.MinimumAddress.HighPart, Desc->u.Memory.MinimumAddress.LowPart,
+ Desc->u.Memory.MaximumAddress.HighPart, Desc->u.Memory.MaximumAddress.LowPart,
+ Desc->u.Memory.Alignment,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Interrupt.MinimumVector,
+ Desc->u.Interrupt.MaximumVector
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA %c Min: %x, Max: %x\n",
+ Indent, c,
+ Desc->u.Dma.MinimumChannel,
+ Desc->u.Dma.MaximumChannel
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpIoResourceList (
+ IN PIO_RESOURCE_REQUIREMENTS_LIST IoList
+ )
+/*++
+
+Routine Description:
+
+ This routine displays Io resource requirements list.
+
+Arguments:
+
+ IoList - supplies a pointer to the Io resource requirements list to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ PIO_RESOURCE_LIST resList;
+ PIO_RESOURCE_DESCRIPTOR resDesc;
+ ULONG listCount, count, i, j;
+
+ DbgPrint("Pnp Bios IO Resource Requirements List for Slot %x -\n", IoList->SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", IoList->AlternativeLists, IoList->BusNumber);
+ listCount = IoList->AlternativeLists;
+ resList = &IoList->List[0];
+ for (i = 0; i < listCount; i++) {
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", resList->Version,
+ resList->Revision, resList->Count);
+ resDesc = &resList->Descriptors[0];
+ count = resList->Count;
+ for (j = 0; j < count; j++) {
+ PipDumpIoResourceDescriptor(" ", resDesc);
+ resDesc++;
+ }
+ resList = (PIO_RESOURCE_LIST) resDesc;
+ }
+}
+
+VOID
+PipDumpCmResourceDescriptor (
+ IN PUCHAR Indent,
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc
+ )
+/*++
+
+Routine Description:
+
+ This routine processes a IO_RESOURCE_DESCRIPTOR and displays it.
+
+Arguments:
+
+ Indent - # char of indentation.
+
+ Desc - supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ switch (Desc->Type) {
+ case CmResourceTypePort:
+ DbgPrint ("%sIO Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Port.Start.HighPart, Desc->u.Port.Start.LowPart,
+ Desc->u.Port.Length
+ );
+ break;
+
+ case CmResourceTypeMemory:
+ DbgPrint ("%sMEM Start: %x:%08x, Length: %x\n",
+ Indent,
+ Desc->u.Memory.Start.HighPart, Desc->u.Memory.Start.LowPart,
+ Desc->u.Memory.Length
+ );
+ break;
+
+ case CmResourceTypeInterrupt:
+ DbgPrint ("%sINT Level: %x, Vector: %x, Affinity: %x\n",
+ Indent,
+ Desc->u.Interrupt.Level,
+ Desc->u.Interrupt.Vector,
+ Desc->u.Interrupt.Affinity
+ );
+ break;
+
+ case CmResourceTypeDma:
+ DbgPrint ("%sDMA Channel: %x, Port: %x\n",
+ Indent,
+ Desc->u.Dma.Channel,
+ Desc->u.Dma.Port
+ );
+ break;
+ }
+}
+
+VOID
+PipDumpCmResourceList (
+ IN PCM_RESOURCE_LIST CmList,
+ IN ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine displays CM resource list.
+
+Arguments:
+
+ CmList - supplies a pointer to CM resource list
+
+ SlotNumber - slot number of the resources
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullDesc;
+ PCM_PARTIAL_RESOURCE_LIST partialDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
+ ULONG count, i;
+
+ fullDesc = &CmList->List[0];
+ DbgPrint("Pnp Bios Cm Resource List for Slot %x -\n", SlotNumber);
+ DbgPrint(" List Count = %x, Bus Number = %x\n", CmList->Count, fullDesc->BusNumber);
+ partialDesc = &fullDesc->PartialResourceList;
+ DbgPrint(" Version = %x, Revision = %x, Desc count = %x\n", partialDesc->Version,
+ partialDesc->Revision, partialDesc->Count);
+ count = partialDesc->Count;
+ desc = &partialDesc->PartialDescriptors[0];
+ for (i = 0; i < count; i++) {
+ PipDumpCmResourceDescriptor(" ", desc);
+ desc++;
+ }
+}
+#endif
diff --git a/private/ntos/nthals/extender/pnpisa/i386/pnpisa.h b/private/ntos/nthals/extender/pnpisa/i386/pnpisa.h
new file mode 100644
index 000000000..b36f77d16
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/pnpisa.h
@@ -0,0 +1,155 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pnpisa.h
+
+Abstract:
+
+ This module contins definitions/declarations for PNP ISA related
+ definitions.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-12-1995
+
+Revision History:
+
+--*/
+
+#ifndef NEC_98
+#define ADDRESS_PORT 0x0279
+#define COMMAND_PORT 0x0a79
+#else
+#define ADDRESS_PORT 0x0259
+#define COMMAND_PORT 0x0a59
+#endif // NEC_98
+
+//
+// Plug and Play Card Control Registers
+//
+
+#define SET_READ_DATA_PORT 0x00
+#define SERIAL_ISOLATION_PORT 0x01
+#define CONFIG_CONTROL_PORT 0x02
+#define WAKE_CSN_PORT 0x03
+#define CONFIG_DATA_PORT 0x04
+#define CONFIG_DATA_STATUS_PORT 0x05
+#define SET_CSN_PORT 0x06
+#define LOGICAL_DEVICE_PORT 0x07
+
+//
+// Plug and Play Logical Device Control Registers
+//
+
+#define ACTIVATE_PORT 0x30
+#define IO_RANGE_CHECK_PORT 0x31
+
+//
+// Config Control command
+//
+
+#define CONTROL_WAIT_FOR_KEY 0x02
+#define CONTROL_RESET_CSN 0x04
+
+//
+// Memory Space Configuration
+//
+
+#define NUMBER_MEMORY_DESCRIPTORS 4
+#define ADDRESS_MEMORY_BASE 0x40
+#define ADDRESS_MEMORY_INCR 0x08
+#define ADDRESS_MEMORY_HI 0x00
+#define ADDRESS_MEMORY_LO 0x01
+#define ADDRESS_MEMORY_CTL 0x02
+#define ADDRESS_MEMORY_CTL_LIMIT 0x01
+#define ADDRESS_MEMORY_UPPER_HI 0x03
+#define ADDRESS_MEMORY_UPPER_LO 0x04
+
+//
+// 32 Bit Memory Space Configuration
+//
+
+#define NUMBER_32_MEMORY_DESCRIPTORS 4
+#define ADDRESS_32_MEMORY_BASE(x) ((PUCHAR)(0x70+((x)*0x10)+((x==0) ? 6 : 0)))
+#define ADDRESS_32_MEMORY_B3 0x0
+#define ADDRESS_32_MEMORY_B2 0x1
+#define ADDRESS_32_MEMORY_B1 0x2
+#define ADDRESS_32_MEMORY_B0 0x3
+#define ADDRESS_32_MEMORY_CTL 0x4
+#define ADDRESS_32_MEMORY_E3 0x5
+#define ADDRESS_32_MEMORY_E2 0x6
+#define ADDRESS_32_MEMORY_E1 0x7
+#define ADDRESS_32_MEMORY_E0 0x8
+
+//
+// Io Space Configuration
+//
+
+#define NUMBER_IO_DESCRIPTORS 8
+#define ADDRESS_IO_BASE 0x60
+#define ADDRESS_IO_INCR 0x02
+#define ADDRESS_IO_BASE_HI 0x00
+#define ADDRESS_IO_BASE_LO 0x01
+
+//
+// Interrupt Configuration
+//
+
+#define NUMBER_IRQ_DESCRIPTORS 2
+#define ADDRESS_IRQ_BASE 0x70
+#define ADDRESS_IRQ_INCR 0x02
+#define ADDRESS_IRQ_VALUE 0x00
+#define ADDRESS_IRQ_TYPE 0x01
+
+//
+// DMA Configuration
+//
+
+#define NUMBER_DMA_DESCRIPTORS 2
+#define ADDRESS_DMA_BASE 0x74
+#define ADDRESS_DMA_INCR 0x01
+#define ADDRESS_DMA_VALUE 0x00
+#define NO_DMA 0x04
+
+//
+// 9 byte serial identifier of a PNP ISA Card
+//
+
+#include "pshpack1.h"
+typedef struct _SERIAL_IDENTIFIER_ {
+ ULONG VenderId;
+ ULONG SerialNumber;
+ UCHAR Checksum;
+} SERIAL_IDENTIFIER, *PSERIAL_IDENTIFIER;
+#include "poppack.h"
+
+//
+// Misc. definitions
+//
+
+#define MIN_READ_DATA_PORT 0x200
+#define MAX_READ_DATA_PORT 0x3ff
+#define MAX_CHARACTER_LENGTH 255
+#define NUMBER_CARD_ID_BYTES 9
+#define NUMBER_CARD_ID_BITS (NUMBER_CARD_ID_BYTES * 8)
+#define CHECKSUMED_BITS 64
+#define LFSR_SEED 0x6A
+#define ISOLATION_TEST_BYTE_1 0x55
+#define ISOLATION_TEST_BYTE_2 0xAA
+
+#define PipWriteAddress(data) WRITE_PORT_UCHAR ((PUCHAR)ADDRESS_PORT, (UCHAR)(data))
+#define PipWriteData(data) WRITE_PORT_UCHAR ((PUCHAR)COMMAND_PORT, (UCHAR)(data))
+#define PipReadData() READ_PORT_UCHAR (PipReadDataPort)
+
+//
+// External references
+//
+
+
+extern PUCHAR PipReadDataPort;
+
+
+
diff --git a/private/ntos/nthals/extender/pnpisa/i386/resource.c b/private/ntos/nthals/extender/pnpisa/i386/resource.c
new file mode 100644
index 000000000..f1b4c2fee
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/i386/resource.c
@@ -0,0 +1,555 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ This module contains the high level device resources support routines.
+
+Author:
+
+ Shie-Lin Tzong (shielint) July-27-1995
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "busp.h"
+#include "pnpisa.h"
+#include "..\..\pnpbios\i386\pbios.h"
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR Buffer
+ );
+
+#define IDBG 1
+
+#pragma alloc_text(PAGE,PipGetCompatibleDeviceId)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceId)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceUniqueId)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceResources)
+#pragma alloc_text(PAGE,PiCtlQueryDeviceResourceRequirements)
+#pragma alloc_text(PAGE,PiCtlSetDeviceResources)
+
+NTSTATUS
+PipGetCompatibleDeviceId (
+ PUCHAR DeviceData,
+ ULONG IdIndex,
+ PWCHAR Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function returns the desired pnp isa id for the specified DeviceData
+ and Id index. If Id index = 0, the Hardware ID will be return; if id
+ index = n, the Nth compatible id will be returned.
+
+Arguments:
+
+ DeviceData - supplies a pointer to the pnp isa device data.
+
+ IdIndex - supplies the index of the compatible id desired.
+
+ Buffer - supplies a pointer to a buffer to receive the compatible Id.
+
+Return Value:
+
+ NTSTATUS code
+
+--*/
+{
+ NTSTATUS status = STATUS_NO_MORE_ENTRIES;
+ UCHAR tag;
+ ULONG count = 0;
+ LONG size;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiString;
+ UCHAR eisaId[8];
+ ULONG id;
+
+ PAGED_CODE();
+
+ tag = *DeviceData;
+
+#if DBG
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+ DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
+ }
+#endif
+
+ if (IdIndex == 0) {
+
+ //
+ // Caller is asking for hardware id
+ //
+
+ DeviceData++; // Skip tag
+ id = *(PULONG)DeviceData;
+ status = STATUS_SUCCESS;
+ } else {
+
+ //
+ // caller is asking for compatible id
+ //
+
+ IdIndex--;
+
+ //
+ // Skip all the resource descriptors to find compatible Id descriptor
+ //
+
+ while (tag != TAG_COMPLETE_END) {
+
+ //
+ // Do we reach the compatible ID descriptor?
+ //
+
+ if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) {
+ if (count == IdIndex) {
+ id = *(PULONG)(DeviceData + 1);
+ status = STATUS_SUCCESS;
+ break;
+ } else {
+ count++;
+ }
+ }
+
+ //
+ // Determine the size of the BIOS resource descriptor and
+ // advance to next resource descriptor.
+ //
+
+ if (!(tag & LARGE_RESOURCE_TAG)) {
+ size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
+ size += 1; // length of small tag
+ } else {
+ size = *(PUSHORT)(DeviceData + 1);
+ size += 3; // length of large tag
+ }
+
+ DeviceData += size;
+ tag = *DeviceData;
+ }
+ }
+
+ if (NT_SUCCESS(status)) {
+ PipDecompressEisaId(id, eisaId);
+ RtlInitAnsiString(&ansiString, eisaId);
+ RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
+ swprintf(Buffer, L"PNPISA\\*%s", unicodeString.Buffer);
+ RtlFreeUnicodeString(&unicodeString);
+ }
+ return status;
+}
+
+VOID
+PiCtlQueryDeviceUniqueId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the unique id for the particular device.
+
+Arguments:
+
+ DeviceData - Device data information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWCHAR deviceId;
+ PUCHAR deviceData;
+ ULONG eisaid;
+
+ PAGED_CODE();
+
+ //
+ // Set up device's unique id.
+ // device unique id = card series number + logical device eisa id in compressed form
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ deviceData = DeviceInfo->DeviceData;
+
+ //
+ // Make sure device data points to Logical Device Id tag
+ //
+
+ if ((*deviceData & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
+
+ //
+ // Can not get the eisa compressed id. Use logical device number instead.
+ //
+#if DBG
+ DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
+#endif
+ eisaid = DeviceInfo->LogicalDeviceNumber;
+ } else {
+
+ //
+ // Get the eisa compressed id for the logical device.
+ //
+
+ deviceData++; // Skip tag
+ eisaid = *(PULONG)deviceData;
+ }
+ swprintf (deviceId,
+ L"%08x%08x",
+ ((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber,
+ eisaid
+ );
+#if IDBG
+ {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, (PWCHAR)Context->DeviceControl.Buffer);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x Unique Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceInfoSlot(DeviceInfo),
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ PipCompleteDeviceControl (STATUS_SUCCESS, Context, DeviceInfo);
+}
+
+VOID
+PiCtlQueryDeviceId (
+ PDEVICE_INFORMATION DeviceInfo,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular device.
+
+Arguments:
+
+ DeviceInfo - Device information for the specificied device.
+
+ Context - Device control context of the request.
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+ PWCHAR deviceId;
+ ULONG idIndex;
+
+ PAGED_CODE();
+
+ //
+ // Determine which device ID the caller wants back
+ //
+
+ idIndex = *((PULONG) Context->DeviceControl.Buffer);
+
+ //
+ // Call worker routine to get the desired Id.
+ //
+
+ deviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ status = PipGetCompatibleDeviceId(DeviceInfo->DeviceData,
+ idIndex,
+ (PWCHAR) deviceId);
+
+#if IDBG
+ if (NT_SUCCESS(status)) {
+ ANSI_STRING ansiString;
+ UNICODE_STRING unicodeString;
+
+ RtlInitUnicodeString(&unicodeString, deviceId);
+ RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
+ DbgPrint("Bus %x Slot %x IdIndex %x Compatible Id = %s\n",
+ Context->Handler->BusNumber,
+ DeviceInfoSlot(DeviceInfo),
+ idIndex,
+ ansiString.Buffer
+ );
+ RtlFreeAnsiString(&ansiString);
+ }
+#endif
+
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
+
+VOID
+PiCtlQueryDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ 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:
+
+ DeviceInfo - Device information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length;
+ PCM_RESOURCE_LIST cmResources;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // protect port access
+ //
+
+ ExAcquireFastMutex(&PipPortMutex);
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber
+ );
+
+ status = PipReadDeviceBootResourceData (
+ Context->Handler->BusNumber,
+ DeviceInfo->DeviceData,
+ &cmResources,
+ &length
+ );
+
+ PipWriteAddress(ACTIVATE_PORT);
+ PipWriteData(0);
+
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ ExReleaseFastMutex(&PipPortMutex);
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ cmResources = (PCM_RESOURCE_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(CM_RESOURCE_LIST), 'iPnP');
+ if (!cmResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ cmResources->Count = 0;
+ cmResources->List[0].InterfaceType = Context->RootHandler->InterfaceType;
+ cmResources->List[0].BusNumber = Context->RootHandler->BusNumber;
+ cmResources->List[0].PartialResourceList.Version = 0;
+ cmResources->List[0].PartialResourceList.Revision = 0;
+ cmResources->List[0].PartialResourceList.Count = 0;
+ length = sizeof(CM_RESOURCE_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, cmResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if IDBG
+ if (NT_SUCCESS(status)) {
+ PipDumpCmResourceList(cmResources, DeviceInfoSlot(DeviceInfo));
+ }
+#endif
+ ExFreePool(cmResources);
+ }
+exitLocal:
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
+
+VOID
+PiCtlQueryDeviceResourceRequirements (
+ PDEVICE_INFORMATION DeviceInfo,
+ 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 - Device data information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ ULONG length = 0;
+ PIO_RESOURCE_REQUIREMENTS_LIST ioResources = NULL;
+ NTSTATUS status;
+ PUCHAR deviceData;
+ PAGED_CODE();
+
+ deviceData = DeviceInfo->DeviceData;
+ status = PbBiosResourcesToNtResources (
+ Context->RootHandler->BusNumber,
+ DeviceInfoSlot(DeviceInfo),
+ &deviceData,
+ &ioResources,
+ &length
+ );
+
+ //
+ // Return results
+ //
+
+ if (NT_SUCCESS(status)) {
+ if (length == 0) {
+
+ //
+ // If resource info is not available, return an empty CM_RESOURCE_LIST
+ //
+
+ ioResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePoolWithTag (
+ PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST), 'bPnP');
+ if (!ioResources) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto exitLocal;
+ } else {
+ ioResources->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ ioResources->InterfaceType = Context->RootHandler->InterfaceType;
+ ioResources->BusNumber = Context->RootHandler->BusNumber;
+ ioResources->SlotNumber = DeviceInfoSlot(DeviceInfo);
+ ioResources->Reserved[0] = 0;
+ ioResources->Reserved[1] = 0;
+ ioResources->Reserved[2] = 0;
+ ioResources->AlternativeLists = 0;
+ ioResources->List[0].Version = 1;
+ ioResources->List[0].Revision = 1;
+ ioResources->List[0].Count = 0;
+ length = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+ }
+ }
+ if (length > *Context->DeviceControl.BufferLength) {
+ status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, ioResources, length);
+ }
+ *Context->DeviceControl.BufferLength = length;
+#if IDBG
+ if (NT_SUCCESS(status)) {
+ PipDumpIoResourceList(ioResources);
+ }
+#endif
+ ExFreePool(ioResources);
+ }
+exitLocal:
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
+
+VOID
+PiCtlSetDeviceResources (
+ PDEVICE_INFORMATION DeviceInfo,
+ 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:
+
+ DeviceInfo - Device information for the specificied slot
+
+ Context - Device control context of the request
+
+Return Value:
+
+ The device control is completed
+
+--*/
+{
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // Protect port access
+ //
+
+ ExAcquireFastMutex(&PipPortMutex);
+
+ PipSelectLogicalDevice(DeviceInfo->CardInformation->CardSelectNumber,
+ DeviceInfo->LogicalDeviceNumber
+ );
+
+ //
+ // Set resource settings for the device
+ //
+
+ status = PipWriteDeviceBootResourceData (
+ DeviceInfo->DeviceData,
+ (PCM_RESOURCE_LIST) Context->DeviceControl.Buffer
+ );
+ //
+ // Put all cards into wait for key state.
+ //
+
+ PipWriteAddress(CONFIG_CONTROL_PORT);
+ PipWriteData(CONTROL_WAIT_FOR_KEY);
+
+ ExReleaseFastMutex(&PipPortMutex);
+ PipCompleteDeviceControl (status, Context, DeviceInfo);
+}
diff --git a/private/ntos/nthals/extender/pnpisa/makefile b/private/ntos/nthals/extender/pnpisa/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/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/pnpisa/pnpisa.rc b/private/ntos/nthals/extender/pnpisa/pnpisa.rc
new file mode 100644
index 000000000..1a87276e5
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/pnpisa.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 "PNP ISA Extension Driver"
+#define VER_INTERNALNAME_STR "pnpisa.sys"
+#define VER_ORIGINALFILENAME_STR "pnpisa.sys"
+
+#include "common.ver"
diff --git a/private/ntos/nthals/extender/pnpisa/sources b/private/ntos/nthals/extender/pnpisa/sources
new file mode 100644
index 000000000..cbea7153e
--- /dev/null
+++ b/private/ntos/nthals/extender/pnpisa/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=extender
+
+TARGETNAME=pnpisa
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+INCLUDES=..\..\..\inc
+
+SOURCES=
+
+i386_SOURCES=pnpisa.rc \
+ i386\bus.c \
+ i386\control.c \
+ i386\data.c \
+ i386\init.c \
+ i386\isolate.c \
+ i386\misc.c \
+ i386\convert.c \
+ i386\resource.c
+
+NTTEST=
+OPTIONAL_NTTEST=
+UMTEST=