summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/extender/pnpisa
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/extender/pnpisa
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/extender/pnpisa')
-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
13 files changed, 6837 insertions, 0 deletions
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=