2001-05-01 23:00:05 +00:00
|
|
|
/*
|
2010-04-07 20:19:29 +00:00
|
|
|
* PROJECT: ReactOS ISA PnP Bus driver
|
2021-03-04 12:42:42 +00:00
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
2010-04-07 20:19:29 +00:00
|
|
|
* PURPOSE: Driver entry
|
2021-03-04 12:42:42 +00:00
|
|
|
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
|
|
|
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
|
2021-03-04 12:48:43 +00:00
|
|
|
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
|
2001-05-01 23:00:05 +00:00
|
|
|
*/
|
2014-02-06 11:18:34 +00:00
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
2024-05-03 13:09:23 +00:00
|
|
|
#ifndef UNIT_TEST
|
2001-05-01 23:00:05 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
#include "isapnp.h"
|
2024-05-03 13:09:23 +00:00
|
|
|
|
2010-04-07 20:19:29 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2001-05-01 23:00:05 +00:00
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
|
|
|
KEVENT BusSyncEvent;
|
|
|
|
|
|
|
|
_Guarded_by_(BusSyncEvent)
|
2021-03-04 12:45:38 +00:00
|
|
|
BOOLEAN ReadPortCreated = FALSE;
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
_Guarded_by_(BusSyncEvent)
|
|
|
|
LIST_ENTRY BusListHead;
|
|
|
|
|
2024-05-03 13:09:23 +00:00
|
|
|
#endif /* UNIT_TEST */
|
|
|
|
|
2024-10-07 14:10:08 +00:00
|
|
|
extern ULONG IsaConfigPorts[2];
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
2021-03-20 14:51:29 +00:00
|
|
|
static
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
IsaConvertIoRequirement(
|
|
|
|
_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
|
|
|
|
_In_ PISAPNP_IO_DESCRIPTION Description)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_IO;
|
|
|
|
if (Description->Information & 0x1)
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
else
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Length = Description->Length;
|
|
|
|
Descriptor->u.Port.Alignment = Description->Alignment;
|
|
|
|
Descriptor->u.Port.MinimumAddress.LowPart = Description->Minimum;
|
|
|
|
Descriptor->u.Port.MaximumAddress.LowPart = Description->Maximum +
|
|
|
|
Description->Length - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
IsaConvertIrqRequirement(
|
|
|
|
_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
|
|
|
|
_In_ PISAPNP_IRQ_DESCRIPTION Description,
|
|
|
|
_In_ ULONG Vector,
|
|
|
|
_In_ BOOLEAN FirstDescriptor)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
if (!FirstDescriptor)
|
|
|
|
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
|
|
|
Descriptor->Type = CmResourceTypeInterrupt;
|
|
|
|
if (Description->Information & 0xC)
|
|
|
|
{
|
|
|
|
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareShared;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
}
|
|
|
|
Descriptor->u.Interrupt.MinimumVector =
|
|
|
|
Descriptor->u.Interrupt.MaximumVector = Vector;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
IsaConvertDmaRequirement(
|
|
|
|
_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
|
|
|
|
_In_ PISAPNP_DMA_DESCRIPTION Description,
|
|
|
|
_In_ ULONG Channel,
|
|
|
|
_In_ BOOLEAN FirstDescriptor)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(Description);
|
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
if (!FirstDescriptor)
|
|
|
|
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
|
|
|
Descriptor->Type = CmResourceTypeDma;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareUndetermined;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */
|
|
|
|
Descriptor->u.Dma.MinimumChannel =
|
|
|
|
Descriptor->u.Dma.MaximumChannel = Channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
IsaConvertMemRangeRequirement(
|
|
|
|
_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
|
|
|
|
_In_ PISAPNP_MEMRANGE_DESCRIPTION Description)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
Descriptor->Type = CmResourceTypeMemory;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_MEMORY_24;
|
|
|
|
if ((Description->Information & 0x40) || !(Description->Information & 0x01))
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
|
|
|
|
else
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
|
|
|
Descriptor->u.Memory.Length = Description->Length << 8;
|
|
|
|
if (Description->Alignment == 0)
|
|
|
|
Descriptor->u.Memory.Alignment = 0x10000;
|
|
|
|
else
|
|
|
|
Descriptor->u.Memory.Alignment = Description->Alignment;
|
|
|
|
Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum << 8;
|
|
|
|
Descriptor->u.Memory.MaximumAddress.LowPart = (Description->Maximum << 8) +
|
|
|
|
(Description->Length << 8) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
IsaConvertMemRange32Requirement(
|
|
|
|
_Out_ PIO_RESOURCE_DESCRIPTOR Descriptor,
|
|
|
|
_In_ PISAPNP_MEMRANGE32_DESCRIPTION Description)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
Descriptor->Type = CmResourceTypeMemory;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_MEMORY_24;
|
|
|
|
if ((Description->Information & 0x40) || !(Description->Information & 0x01))
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
|
|
|
|
else
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
|
|
|
Descriptor->u.Memory.Length = Description->Length;
|
|
|
|
Descriptor->u.Memory.Alignment = Description->Alignment;
|
|
|
|
Descriptor->u.Memory.MinimumAddress.LowPart = Description->Minimum;
|
|
|
|
Descriptor->u.Memory.MaximumAddress.LowPart = Description->Maximum +
|
|
|
|
Description->Length - 1;
|
|
|
|
}
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
/*
|
|
|
|
* For example, the PnP ROM
|
|
|
|
* 0x15, 0x04, ... // Logical device ID
|
|
|
|
* 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x04, 0x04, // IO 330, len 4, align 4
|
|
|
|
* 0x30, // **** Start DF ****
|
|
|
|
* 0x22, 0x04, 0x00, // IRQ 2
|
|
|
|
* 0x31, 0x02, // **** Start DF ****
|
|
|
|
* 0x22, 0xC0, 0x00, // IRQ 6 or 7
|
|
|
|
* 0x38, // **** End DF ******
|
|
|
|
* 0x2A, 0x20, 0x3A, // DMA 5
|
|
|
|
* 0x22, 0x00, 0x08, // IRQ 12
|
|
|
|
* 0x79, 0x00, // END
|
|
|
|
*
|
|
|
|
* becomes the following resource requirements list:
|
|
|
|
* Interface 1 Bus 0 Slot 0 AlternativeLists 2
|
|
|
|
*
|
|
|
|
* AltList #0, AltList->Count 4
|
|
|
|
* [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4
|
|
|
|
* [Option 0, ShareDisposition 1, Flags 1] INT: Min 2 Max 2
|
|
|
|
* [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5
|
|
|
|
* [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B
|
|
|
|
*
|
|
|
|
* AltList #1, AltList->Count 5
|
|
|
|
* [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4
|
|
|
|
* [Option 0, ShareDisposition 1, Flags 1] INT: Min 6 Max 6
|
|
|
|
* [Option 8, ShareDisposition 1, Flags 1] INT: Min 7 Max 7
|
|
|
|
* [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5
|
|
|
|
* [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B
|
|
|
|
*/
|
2020-03-22 13:20:52 +00:00
|
|
|
static
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("PAGE")
|
2020-03-22 13:20:52 +00:00
|
|
|
NTSTATUS
|
2021-03-04 12:42:42 +00:00
|
|
|
IsaPnpCreateLogicalDeviceRequirements(
|
|
|
|
_In_ PISAPNP_PDO_EXTENSION PdoExt)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
|
|
|
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
2024-05-03 14:39:26 +00:00
|
|
|
ISAPNP_DEPENDENT_FUNCTION_STATE DfState;
|
|
|
|
ULONG FirstFixedDescriptors, LastFixedDescriptors;
|
|
|
|
ULONG ResourceCount, AltListCount, ListSize, i;
|
|
|
|
BOOLEAN IsFirstAltList, IsFirstDescriptor;
|
|
|
|
PIO_RESOURCE_LIST AltList;
|
|
|
|
PISAPNP_RESOURCE Resource;
|
2020-03-22 13:20:52 +00:00
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
/* Count the number of requirements */
|
|
|
|
DfState = dfNotStarted;
|
|
|
|
FirstFixedDescriptors = 0;
|
|
|
|
LastFixedDescriptors = 0;
|
|
|
|
ResourceCount = 0;
|
|
|
|
AltListCount = 1;
|
|
|
|
Resource = PdoExt->IsaPnpDevice->Resources;
|
|
|
|
while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
switch (Resource->Type)
|
|
|
|
{
|
|
|
|
case ISAPNP_RESOURCE_TYPE_START_DEPENDENT:
|
|
|
|
{
|
|
|
|
if (DfState == dfStarted)
|
|
|
|
++AltListCount;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
DfState = dfStarted;
|
|
|
|
break;
|
|
|
|
}
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
case ISAPNP_RESOURCE_TYPE_END_DEPENDENT:
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
DfState = dfDone;
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
case ISAPNP_RESOURCE_TYPE_IRQ:
|
|
|
|
case ISAPNP_RESOURCE_TYPE_DMA:
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
RTL_BITMAP ResourceBitmap;
|
|
|
|
ULONG BitmapSize, BitmapBuffer, BitCount;
|
|
|
|
|
|
|
|
if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ)
|
|
|
|
{
|
|
|
|
BitmapSize = RTL_BITS_OF(Resource->IrqDescription.Mask);
|
|
|
|
BitmapBuffer = Resource->IrqDescription.Mask;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BitmapSize = RTL_BITS_OF(Resource->DmaDescription.Mask);
|
|
|
|
BitmapBuffer = Resource->DmaDescription.Mask;
|
|
|
|
}
|
|
|
|
RtlInitializeBitMap(&ResourceBitmap, &BitmapBuffer, BitmapSize);
|
|
|
|
|
|
|
|
BitCount = RtlNumberOfSetBits(&ResourceBitmap);
|
|
|
|
switch (DfState)
|
|
|
|
{
|
|
|
|
case dfNotStarted:
|
|
|
|
FirstFixedDescriptors += BitCount;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dfStarted:
|
|
|
|
ResourceCount += BitCount;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dfDone:
|
|
|
|
LastFixedDescriptors += BitCount;
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT_UNREACHABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
case ISAPNP_RESOURCE_TYPE_IO:
|
|
|
|
case ISAPNP_RESOURCE_TYPE_MEMRANGE:
|
|
|
|
case ISAPNP_RESOURCE_TYPE_MEMRANGE32:
|
|
|
|
{
|
|
|
|
switch (DfState)
|
|
|
|
{
|
|
|
|
case dfNotStarted:
|
|
|
|
++FirstFixedDescriptors;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dfStarted:
|
|
|
|
++ResourceCount;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dfDone:
|
|
|
|
++LastFixedDescriptors;
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT_UNREACHABLE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
ASSERT(FALSE);
|
|
|
|
UNREACHABLE;
|
|
|
|
break;
|
2020-03-22 13:20:52 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
++Resource;
|
2020-03-22 13:20:52 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
/* This logical device has no resource requirements */
|
|
|
|
if ((ResourceCount == 0) && (FirstFixedDescriptors == 0) && (LastFixedDescriptors == 0))
|
2020-03-22 13:20:52 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/* Allocate memory to store requirements */
|
2024-05-03 14:39:26 +00:00
|
|
|
ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
|
|
|
|
FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) * AltListCount +
|
|
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * ResourceCount +
|
|
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * AltListCount *
|
|
|
|
(FirstFixedDescriptors + LastFixedDescriptors);
|
2021-03-04 12:43:19 +00:00
|
|
|
RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
|
2020-03-22 13:20:52 +00:00
|
|
|
if (!RequirementsList)
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
|
|
|
RequirementsList->ListSize = ListSize;
|
|
|
|
RequirementsList->InterfaceType = Isa;
|
2024-05-03 14:39:26 +00:00
|
|
|
RequirementsList->AlternativeLists = AltListCount;
|
2020-03-22 13:20:52 +00:00
|
|
|
|
|
|
|
RequirementsList->List[0].Version = 1;
|
|
|
|
RequirementsList->List[0].Revision = 1;
|
|
|
|
|
|
|
|
/* Store requirements */
|
2024-05-03 14:39:26 +00:00
|
|
|
IsFirstAltList = TRUE;
|
|
|
|
AltList = &RequirementsList->List[0];
|
|
|
|
Descriptor = &RequirementsList->List[0].Descriptors[0];
|
|
|
|
Resource = PdoExt->IsaPnpDevice->Resources;
|
|
|
|
while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
switch (Resource->Type)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
case ISAPNP_RESOURCE_TYPE_START_DEPENDENT:
|
|
|
|
{
|
|
|
|
if (!IsFirstAltList)
|
|
|
|
{
|
|
|
|
/* Add room for the fixed descriptors */
|
|
|
|
AltList->Count += LastFixedDescriptors;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
/* Move on to the next list */
|
|
|
|
AltList = (PIO_RESOURCE_LIST)(AltList->Descriptors + AltList->Count);
|
|
|
|
AltList->Version = 1;
|
|
|
|
AltList->Revision = 1;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
/* Propagate the fixed resources to our new list */
|
|
|
|
RtlCopyMemory(&AltList->Descriptors,
|
|
|
|
RequirementsList->List[0].Descriptors,
|
|
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * FirstFixedDescriptors);
|
|
|
|
AltList->Count += FirstFixedDescriptors;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
Descriptor = &AltList->Descriptors[FirstFixedDescriptors];
|
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
IsFirstAltList = FALSE;
|
|
|
|
break;
|
2020-03-22 22:23:04 +00:00
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
case ISAPNP_RESOURCE_TYPE_END_DEPENDENT:
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
case ISAPNP_RESOURCE_TYPE_IO:
|
2020-03-22 22:23:04 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
IsaConvertIoRequirement(Descriptor++, &Resource->IoDescription);
|
|
|
|
|
|
|
|
++AltList->Count;
|
|
|
|
break;
|
2020-03-22 22:23:04 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
case ISAPNP_RESOURCE_TYPE_IRQ:
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
IsFirstDescriptor = TRUE;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
for (i = 0; i < RTL_BITS_OF(Resource->IrqDescription.Mask); i++)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
if (!(Resource->IrqDescription.Mask & (1 << i)))
|
2021-03-20 14:51:29 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
IsaConvertIrqRequirement(Descriptor++,
|
2024-05-03 14:39:26 +00:00
|
|
|
&Resource->IrqDescription,
|
|
|
|
i,
|
|
|
|
IsFirstDescriptor);
|
|
|
|
++AltList->Count;
|
|
|
|
|
|
|
|
IsFirstDescriptor = FALSE;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
case ISAPNP_RESOURCE_TYPE_DMA:
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
IsFirstDescriptor = TRUE;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
for (i = 0; i < RTL_BITS_OF(Resource->DmaDescription.Mask); i++)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
if (!(Resource->DmaDescription.Mask & (1 << i)))
|
2021-03-20 14:51:29 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
IsaConvertDmaRequirement(Descriptor++,
|
2024-05-03 14:39:26 +00:00
|
|
|
&Resource->DmaDescription,
|
|
|
|
i,
|
|
|
|
IsFirstDescriptor);
|
|
|
|
++AltList->Count;
|
|
|
|
|
|
|
|
IsFirstDescriptor = FALSE;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
case ISAPNP_RESOURCE_TYPE_MEMRANGE:
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
IsaConvertMemRangeRequirement(Descriptor++, &Resource->MemRangeDescription);
|
|
|
|
|
|
|
|
++AltList->Count;
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
case ISAPNP_RESOURCE_TYPE_MEMRANGE32:
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
IsaConvertMemRange32Requirement(Descriptor++, &Resource->MemRange32Description);
|
|
|
|
|
|
|
|
++AltList->Count;
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
default:
|
|
|
|
ASSERT(FALSE);
|
|
|
|
UNREACHABLE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++Resource;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append the fixed resources */
|
|
|
|
if (LastFixedDescriptors)
|
|
|
|
{
|
|
|
|
PIO_RESOURCE_LIST NextList = &RequirementsList->List[0];
|
|
|
|
|
|
|
|
/* Make the descriptor point to the fixed resources */
|
|
|
|
Descriptor -= LastFixedDescriptors;
|
|
|
|
|
|
|
|
/* Propagate the fixed resources onto previous lists */
|
|
|
|
AltListCount = RequirementsList->AlternativeLists - 1;
|
|
|
|
for (i = 0; i < AltListCount; i++)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(&NextList->Descriptors[NextList->Count - LastFixedDescriptors],
|
|
|
|
Descriptor,
|
|
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * LastFixedDescriptors);
|
|
|
|
|
2021-03-20 14:51:29 +00:00
|
|
|
NextList = (PIO_RESOURCE_LIST)(NextList->Descriptors + NextList->Count);
|
2020-03-22 22:23:04 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-22 13:20:52 +00:00
|
|
|
|
|
|
|
PdoExt->RequirementsList = RequirementsList;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-03-20 14:51:29 +00:00
|
|
|
CODE_SEG("PAGE")
|
|
|
|
BOOLEAN
|
|
|
|
FindIoDescriptor(
|
|
|
|
_In_ PISAPNP_LOGICAL_DEVICE LogDevice,
|
|
|
|
_In_opt_ ULONG Base,
|
|
|
|
_In_ ULONG RangeStart,
|
|
|
|
_In_ ULONG RangeEnd,
|
|
|
|
_Out_opt_ PUCHAR Information,
|
2024-05-03 14:39:26 +00:00
|
|
|
_Out_opt_ PULONG Length)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
PISAPNP_RESOURCE Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
Resource = LogDevice->Resources;
|
|
|
|
while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
if (Resource->Type == ISAPNP_RESOURCE_TYPE_IO)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
PISAPNP_IO_DESCRIPTION Description = &Resource->IoDescription;
|
|
|
|
BOOLEAN Match;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
if (Base)
|
|
|
|
{
|
|
|
|
Match = (Base >= Description->Minimum) && (Base <= Description->Maximum);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Match = (RangeStart >= Description->Minimum) &&
|
|
|
|
(RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1));
|
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
if (Match)
|
|
|
|
{
|
|
|
|
if (Information)
|
|
|
|
*Information = Description->Information;
|
|
|
|
if (Length)
|
|
|
|
*Length = Description->Length;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
++Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
BOOLEAN
|
|
|
|
FindIrqDescriptor(
|
|
|
|
_In_ PISAPNP_LOGICAL_DEVICE LogDevice,
|
2024-05-03 14:39:26 +00:00
|
|
|
_In_ ULONG Vector)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
PISAPNP_RESOURCE Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
Resource = LogDevice->Resources;
|
|
|
|
while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
PISAPNP_IRQ_DESCRIPTION Description = &Resource->IrqDescription;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
if (Description->Mask & (1 << Vector))
|
|
|
|
return TRUE;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
++Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
BOOLEAN
|
|
|
|
FindDmaDescriptor(
|
|
|
|
_In_ PISAPNP_LOGICAL_DEVICE LogDevice,
|
2024-05-03 14:39:26 +00:00
|
|
|
_In_ ULONG Channel)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
PISAPNP_RESOURCE Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
Resource = LogDevice->Resources;
|
|
|
|
while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
if (Resource->Type == ISAPNP_RESOURCE_TYPE_DMA)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
PISAPNP_DMA_DESCRIPTION Description = &Resource->DmaDescription;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
if (Description->Mask & (1 << Channel))
|
|
|
|
return TRUE;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
++Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
BOOLEAN
|
|
|
|
FindMemoryDescriptor(
|
|
|
|
_In_ PISAPNP_LOGICAL_DEVICE LogDevice,
|
|
|
|
_In_ ULONG RangeStart,
|
|
|
|
_In_ ULONG RangeEnd,
|
2024-05-03 14:39:26 +00:00
|
|
|
_Out_opt_ PUCHAR Information)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
PISAPNP_RESOURCE Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
Resource = LogDevice->Resources;
|
|
|
|
while (Resource->Type != ISAPNP_RESOURCE_TYPE_END)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
switch (Resource->Type)
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
case ISAPNP_RESOURCE_TYPE_MEMRANGE:
|
|
|
|
{
|
|
|
|
PISAPNP_MEMRANGE_DESCRIPTION Description;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
Description = &Resource->MemRangeDescription;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
if ((RangeStart >= (ULONG)(Description->Minimum << 8)) &&
|
|
|
|
(RangeEnd <= (ULONG)((Description->Maximum << 8) +
|
|
|
|
(Description->Length << 8) - 1)))
|
|
|
|
{
|
|
|
|
if (Information)
|
|
|
|
*Information = Description->Information;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
case ISAPNP_RESOURCE_TYPE_MEMRANGE32:
|
|
|
|
{
|
|
|
|
PISAPNP_MEMRANGE32_DESCRIPTION Description32;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
2024-05-03 14:39:26 +00:00
|
|
|
Description32 = &Resource->MemRange32Description;
|
|
|
|
|
|
|
|
if ((RangeStart >= Description32->Minimum) &&
|
|
|
|
(RangeEnd <= (Description32->Maximum + Description32->Length - 1)))
|
|
|
|
{
|
|
|
|
if (Information)
|
|
|
|
*Information = Description32->Information;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
2024-05-03 14:39:26 +00:00
|
|
|
|
|
|
|
++Resource;
|
2021-03-20 14:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2020-03-22 13:20:52 +00:00
|
|
|
static
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("PAGE")
|
2020-03-22 13:20:52 +00:00
|
|
|
NTSTATUS
|
2021-03-04 12:42:42 +00:00
|
|
|
IsaPnpCreateLogicalDeviceResources(
|
|
|
|
_In_ PISAPNP_PDO_EXTENSION PdoExt)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
|
|
|
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
|
|
|
|
ULONG ResourceCount = 0;
|
2021-03-20 14:51:29 +00:00
|
|
|
UCHAR Information;
|
2020-03-22 13:20:52 +00:00
|
|
|
ULONG ListSize, i;
|
|
|
|
PCM_RESOURCE_LIST ResourceList;
|
|
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
2021-03-20 14:51:29 +00:00
|
|
|
if (!(LogDev->Flags & ISAPNP_HAS_RESOURCES))
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
2020-03-22 13:20:52 +00:00
|
|
|
/* Count number of required resources */
|
2021-03-04 12:42:42 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
|
|
|
if (LogDev->Io[i].CurrentBase)
|
|
|
|
ResourceCount++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2021-03-04 12:42:42 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
|
|
|
if (LogDev->Irq[i].CurrentNo)
|
|
|
|
ResourceCount++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2021-03-04 12:42:42 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++)
|
2020-03-22 22:23:04 +00:00
|
|
|
{
|
2024-05-03 14:42:21 +00:00
|
|
|
if (LogDev->Dma[i].CurrentChannel != DMACHANNEL_NONE)
|
2020-03-22 22:23:04 +00:00
|
|
|
ResourceCount++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++)
|
|
|
|
{
|
|
|
|
if (LogDev->MemRange[i].CurrentBase)
|
|
|
|
ResourceCount++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++)
|
|
|
|
{
|
|
|
|
if (LogDev->MemRange32[i].CurrentBase)
|
|
|
|
ResourceCount++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2020-03-22 13:20:52 +00:00
|
|
|
if (ResourceCount == 0)
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/* Allocate memory to store resources */
|
|
|
|
ListSize = sizeof(CM_RESOURCE_LIST)
|
2021-03-04 12:42:42 +00:00
|
|
|
+ (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
2021-03-04 12:43:19 +00:00
|
|
|
ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
|
2020-03-22 13:20:52 +00:00
|
|
|
if (!ResourceList)
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
|
|
|
ResourceList->Count = 1;
|
|
|
|
ResourceList->List[0].InterfaceType = Isa;
|
|
|
|
ResourceList->List[0].PartialResourceList.Version = 1;
|
|
|
|
ResourceList->List[0].PartialResourceList.Revision = 1;
|
|
|
|
ResourceList->List[0].PartialResourceList.Count = ResourceCount;
|
|
|
|
|
|
|
|
/* Store resources */
|
|
|
|
ResourceCount = 0;
|
2021-03-04 12:42:42 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
2021-03-20 14:51:29 +00:00
|
|
|
ULONG CurrentLength;
|
|
|
|
|
2020-03-22 13:20:52 +00:00
|
|
|
if (!LogDev->Io[i].CurrentBase)
|
2021-03-04 12:47:16 +00:00
|
|
|
break;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2021-03-20 14:51:29 +00:00
|
|
|
if (!FindIoDescriptor(LogDev,
|
|
|
|
LogDev->Io[i].CurrentBase,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
&Information,
|
2024-05-03 14:39:26 +00:00
|
|
|
&CurrentLength))
|
2021-03-20 14:51:29 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
DPRINT1("I/O entry #%lu %x not found\n", i, LogDev->Io[i].CurrentBase);
|
2021-03-20 14:51:29 +00:00
|
|
|
goto InvalidBiosResources;
|
|
|
|
}
|
|
|
|
|
2020-03-22 13:20:52 +00:00
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
2021-03-20 14:51:29 +00:00
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_IO;
|
|
|
|
if (Information & 0x1)
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
|
2020-03-22 13:20:52 +00:00
|
|
|
else
|
2021-03-20 14:51:29 +00:00
|
|
|
Descriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Length = CurrentLength;
|
2020-03-22 13:20:52 +00:00
|
|
|
Descriptor->u.Port.Start.LowPart = LogDev->Io[i].CurrentBase;
|
|
|
|
}
|
2021-03-04 12:42:42 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++)
|
2020-03-22 13:20:52 +00:00
|
|
|
{
|
|
|
|
if (!LogDev->Irq[i].CurrentNo)
|
2021-03-04 12:47:16 +00:00
|
|
|
break;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2020-03-22 13:20:52 +00:00
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
|
|
|
|
Descriptor->Type = CmResourceTypeInterrupt;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
if (LogDev->Irq[i].CurrentType & 0x01)
|
|
|
|
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
|
|
|
else
|
|
|
|
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
|
|
|
Descriptor->u.Interrupt.Level = LogDev->Irq[i].CurrentNo;
|
|
|
|
Descriptor->u.Interrupt.Vector = LogDev->Irq[i].CurrentNo;
|
2024-05-03 14:39:26 +00:00
|
|
|
Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1;
|
2020-03-22 13:20:52 +00:00
|
|
|
}
|
2021-03-04 12:42:42 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++)
|
2020-03-22 22:23:04 +00:00
|
|
|
{
|
2024-05-03 14:42:21 +00:00
|
|
|
if (LogDev->Dma[i].CurrentChannel == DMACHANNEL_NONE)
|
2021-03-04 12:47:16 +00:00
|
|
|
break;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2020-03-22 22:23:04 +00:00
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
|
|
|
|
Descriptor->Type = CmResourceTypeDma;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
2021-03-20 14:51:29 +00:00
|
|
|
Descriptor->Flags = CM_RESOURCE_DMA_8; /* Ignore information byte for compatibility */
|
|
|
|
Descriptor->u.Dma.Channel = LogDev->Dma[i].CurrentChannel;
|
|
|
|
}
|
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++)
|
|
|
|
{
|
|
|
|
if (!LogDev->MemRange[i].CurrentBase)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (!FindMemoryDescriptor(LogDev,
|
|
|
|
LogDev->MemRange[i].CurrentBase,
|
|
|
|
LogDev->MemRange[i].CurrentLength,
|
2024-05-03 14:39:26 +00:00
|
|
|
&Information))
|
2020-03-22 22:23:04 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
DPRINT1("MEM entry #%lu %lx %lx not found\n",
|
|
|
|
i,
|
|
|
|
LogDev->MemRange[i].CurrentBase,
|
|
|
|
LogDev->MemRange[i].CurrentLength);
|
2021-03-20 14:51:29 +00:00
|
|
|
goto InvalidBiosResources;
|
2020-03-22 22:23:04 +00:00
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
|
|
|
|
Descriptor->Type = CmResourceTypeMemory;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_MEMORY_24;
|
|
|
|
if ((Information & 0x40) || !(Information & 0x01))
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
|
|
|
|
else
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
2024-05-03 14:08:33 +00:00
|
|
|
Descriptor->u.Memory.Length = LogDev->MemRange[i].CurrentLength;
|
2021-03-20 14:51:29 +00:00
|
|
|
Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange[i].CurrentBase;
|
|
|
|
}
|
|
|
|
for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++)
|
|
|
|
{
|
|
|
|
if (!LogDev->MemRange32[i].CurrentBase)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (!FindMemoryDescriptor(LogDev,
|
|
|
|
LogDev->MemRange32[i].CurrentBase,
|
|
|
|
LogDev->MemRange32[i].CurrentLength,
|
2024-05-03 14:39:26 +00:00
|
|
|
&Information))
|
2020-03-22 22:23:04 +00:00
|
|
|
{
|
2024-05-03 14:39:26 +00:00
|
|
|
DPRINT1("MEM32 entry #%lu %lx %lx not found\n",
|
|
|
|
i,
|
|
|
|
LogDev->MemRange32[i].CurrentBase,
|
|
|
|
LogDev->MemRange32[i].CurrentLength);
|
2021-03-20 14:51:29 +00:00
|
|
|
goto InvalidBiosResources;
|
2020-03-22 22:23:04 +00:00
|
|
|
}
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
|
|
|
|
Descriptor->Type = CmResourceTypeMemory;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_MEMORY_24;
|
|
|
|
if ((Information & 0x40) || !(Information & 0x01))
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
|
|
|
|
else
|
|
|
|
Descriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
2024-05-03 14:08:33 +00:00
|
|
|
Descriptor->u.Memory.Length = LogDev->MemRange32[i].CurrentLength;
|
2021-03-20 14:51:29 +00:00
|
|
|
Descriptor->u.Memory.Start.QuadPart = LogDev->MemRange32[i].CurrentBase;
|
2020-03-22 22:23:04 +00:00
|
|
|
}
|
2020-03-22 13:20:52 +00:00
|
|
|
|
|
|
|
PdoExt->ResourceList = ResourceList;
|
|
|
|
PdoExt->ResourceListSize = ListSize;
|
|
|
|
return STATUS_SUCCESS;
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
InvalidBiosResources:
|
2024-05-03 14:39:26 +00:00
|
|
|
DPRINT1("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev->CSN, LogDev->LDN);
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
LogDev->Flags &= ~ISAPNP_HAS_RESOURCES;
|
|
|
|
ExFreePoolWithTag(ResourceList, TAG_ISAPNP);
|
|
|
|
return STATUS_SUCCESS;
|
2020-03-22 13:20:52 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("PAGE")
|
2023-01-15 16:41:49 +00:00
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST
|
2020-03-21 15:58:21 +00:00
|
|
|
IsaPnpCreateReadPortDORequirements(
|
2021-03-28 17:29:02 +00:00
|
|
|
_In_opt_ ULONG SelectedReadPort)
|
2020-03-21 15:58:21 +00:00
|
|
|
{
|
2021-03-28 17:29:02 +00:00
|
|
|
ULONG ResourceCount, ListSize, i;
|
2020-03-21 15:58:21 +00:00
|
|
|
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
|
|
|
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
2021-03-28 17:29:02 +00:00
|
|
|
const ULONG ReadPorts[] = { 0x274, 0x3E4, 0x204, 0x2E4, 0x354, 0x2F4 };
|
2020-03-21 15:58:21 +00:00
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
2021-03-28 17:29:02 +00:00
|
|
|
if (SelectedReadPort)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* [IO descriptor: ISAPNP_WRITE_DATA, required]
|
|
|
|
* [IO descriptor: ISAPNP_WRITE_DATA, optional]
|
|
|
|
* [IO descriptor: ISAPNP_ADDRESS, required]
|
|
|
|
* [IO descriptor: ISAPNP_ADDRESS, optional]
|
|
|
|
* [IO descriptor: Selected Read Port, required]
|
|
|
|
* [IO descriptor: Read Port 1, optional]
|
|
|
|
* [IO descriptor: Read Port 2, optional]
|
|
|
|
* [...]
|
|
|
|
* [IO descriptor: Read Port X - 1, optional]
|
|
|
|
*/
|
2024-10-07 14:10:08 +00:00
|
|
|
ResourceCount = RTL_NUMBER_OF(IsaConfigPorts) * 2 + RTL_NUMBER_OF(ReadPorts);
|
2021-03-28 17:29:02 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* [IO descriptor: ISAPNP_WRITE_DATA, required]
|
|
|
|
* [IO descriptor: ISAPNP_WRITE_DATA, optional]
|
|
|
|
* [IO descriptor: ISAPNP_ADDRESS, required]
|
|
|
|
* [IO descriptor: ISAPNP_ADDRESS, optional]
|
|
|
|
* [IO descriptor: Read Port 1, required]
|
|
|
|
* [IO descriptor: Read Port 1, optional]
|
|
|
|
* [IO descriptor: Read Port 2, required]
|
|
|
|
* [IO descriptor: Read Port 2, optional]
|
|
|
|
* [...]
|
|
|
|
* [IO descriptor: Read Port X, required]
|
|
|
|
* [IO descriptor: Read Port X, optional]
|
|
|
|
*/
|
2024-10-07 14:10:08 +00:00
|
|
|
ResourceCount = (RTL_NUMBER_OF(IsaConfigPorts) + RTL_NUMBER_OF(ReadPorts)) * 2;
|
2021-03-28 17:29:02 +00:00
|
|
|
}
|
|
|
|
ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
|
|
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1);
|
2021-03-04 12:43:19 +00:00
|
|
|
RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
|
2020-03-21 15:58:21 +00:00
|
|
|
if (!RequirementsList)
|
2023-01-15 16:41:49 +00:00
|
|
|
return NULL;
|
2020-03-21 15:58:21 +00:00
|
|
|
|
|
|
|
RequirementsList->ListSize = ListSize;
|
|
|
|
RequirementsList->AlternativeLists = 1;
|
|
|
|
|
|
|
|
RequirementsList->List[0].Version = 1;
|
|
|
|
RequirementsList->List[0].Revision = 1;
|
2021-03-28 17:29:02 +00:00
|
|
|
RequirementsList->List[0].Count = ResourceCount;
|
|
|
|
|
|
|
|
Descriptor = &RequirementsList->List[0].Descriptors[0];
|
|
|
|
|
|
|
|
/* Store the Data port and the Address port */
|
2024-10-07 14:10:08 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(IsaConfigPorts) * 2; i++)
|
2021-03-28 17:29:02 +00:00
|
|
|
{
|
|
|
|
if ((i % 2) == 0)
|
|
|
|
{
|
|
|
|
/* Expected port */
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Length = 0x01;
|
|
|
|
Descriptor->u.Port.Alignment = 0x01;
|
|
|
|
Descriptor->u.Port.MinimumAddress.LowPart =
|
2024-10-07 14:10:08 +00:00
|
|
|
Descriptor->u.Port.MaximumAddress.LowPart = IsaConfigPorts[i / 2];
|
2021-03-28 17:29:02 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* ... but mark it as optional */
|
|
|
|
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Alignment = 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
Descriptor++;
|
|
|
|
}
|
2020-03-21 15:58:21 +00:00
|
|
|
|
2021-03-28 17:29:02 +00:00
|
|
|
/* Store the Read Ports */
|
|
|
|
if (SelectedReadPort)
|
2020-03-21 15:58:21 +00:00
|
|
|
{
|
2021-03-28 17:29:02 +00:00
|
|
|
BOOLEAN Selected = FALSE;
|
|
|
|
|
|
|
|
DBG_UNREFERENCED_LOCAL_VARIABLE(Selected);
|
|
|
|
|
|
|
|
for (i = 0; i < RTL_NUMBER_OF(ReadPorts); i++)
|
|
|
|
{
|
|
|
|
if (ReadPorts[i] != SelectedReadPort)
|
|
|
|
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
|
|
|
else
|
|
|
|
Selected = TRUE;
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Length = 0x04;
|
|
|
|
Descriptor->u.Port.Alignment = 0x01;
|
|
|
|
Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i];
|
|
|
|
Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i] +
|
|
|
|
Descriptor->u.Port.Length - 1;
|
|
|
|
|
|
|
|
Descriptor++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(Selected == TRUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < RTL_NUMBER_OF(ReadPorts) * 2; i++)
|
|
|
|
{
|
|
|
|
if ((i % 2) == 0)
|
|
|
|
{
|
|
|
|
/* Expected port */
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Length = 0x04;
|
|
|
|
Descriptor->u.Port.Alignment = 0x01;
|
|
|
|
Descriptor->u.Port.MinimumAddress.LowPart = ReadPorts[i / 2];
|
|
|
|
Descriptor->u.Port.MaximumAddress.LowPart = ReadPorts[i / 2] +
|
|
|
|
Descriptor->u.Port.Length - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* ... but mark it as optional */
|
|
|
|
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Alignment = 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
Descriptor++;
|
|
|
|
}
|
2020-03-21 15:58:21 +00:00
|
|
|
}
|
|
|
|
|
2023-01-15 16:41:49 +00:00
|
|
|
return RequirementsList;
|
2020-03-21 15:58:21 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("PAGE")
|
2023-01-15 16:41:49 +00:00
|
|
|
PCM_RESOURCE_LIST
|
|
|
|
IsaPnpCreateReadPortDOResources(VOID)
|
2020-03-21 16:37:45 +00:00
|
|
|
{
|
|
|
|
ULONG ListSize, i;
|
|
|
|
PCM_RESOURCE_LIST ResourceList;
|
|
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
|
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
2021-03-04 12:42:42 +00:00
|
|
|
ListSize = sizeof(CM_RESOURCE_LIST) +
|
2024-10-07 14:10:08 +00:00
|
|
|
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (RTL_NUMBER_OF(IsaConfigPorts) - 1);
|
2021-03-04 12:43:19 +00:00
|
|
|
ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
|
2020-03-21 16:37:45 +00:00
|
|
|
if (!ResourceList)
|
2023-01-15 16:41:49 +00:00
|
|
|
return NULL;
|
2020-03-21 16:37:45 +00:00
|
|
|
|
|
|
|
ResourceList->Count = 1;
|
|
|
|
ResourceList->List[0].InterfaceType = Internal;
|
|
|
|
ResourceList->List[0].PartialResourceList.Version = 1;
|
|
|
|
ResourceList->List[0].PartialResourceList.Revision = 1;
|
2024-10-07 14:10:08 +00:00
|
|
|
ResourceList->List[0].PartialResourceList.Count = RTL_NUMBER_OF(IsaConfigPorts);
|
2020-03-21 16:37:45 +00:00
|
|
|
|
2021-03-20 14:51:29 +00:00
|
|
|
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
|
2024-10-07 14:10:08 +00:00
|
|
|
for (i = 0; i < RTL_NUMBER_OF(IsaConfigPorts); i++)
|
2020-03-21 16:37:45 +00:00
|
|
|
{
|
|
|
|
Descriptor->Type = CmResourceTypePort;
|
|
|
|
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
|
|
Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
Descriptor->u.Port.Length = 0x01;
|
2024-10-07 14:10:08 +00:00
|
|
|
Descriptor->u.Port.Start.LowPart = IsaConfigPorts[i];
|
2021-03-20 14:51:29 +00:00
|
|
|
|
|
|
|
Descriptor++;
|
2020-03-21 16:37:45 +00:00
|
|
|
}
|
|
|
|
|
2023-01-15 16:41:49 +00:00
|
|
|
return ResourceList;
|
2020-03-21 16:37:45 +00:00
|
|
|
}
|
|
|
|
|
2024-05-03 13:09:23 +00:00
|
|
|
#ifndef UNIT_TEST
|
|
|
|
|
2020-03-16 18:24:07 +00:00
|
|
|
static
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("PAGE")
|
2020-03-16 18:24:07 +00:00
|
|
|
NTSTATUS
|
2021-03-04 12:42:42 +00:00
|
|
|
IsaPnpCreateReadPortDO(
|
|
|
|
_In_ PISAPNP_FDO_EXTENSION FdoExt)
|
2020-03-16 18:24:07 +00:00
|
|
|
{
|
2020-03-21 12:39:20 +00:00
|
|
|
PISAPNP_PDO_EXTENSION PdoExt;
|
|
|
|
NTSTATUS Status;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
PAGED_CODE();
|
2021-03-04 12:45:38 +00:00
|
|
|
ASSERT(ReadPortCreated == FALSE);
|
|
|
|
|
|
|
|
DPRINT("Creating Read Port\n");
|
2021-03-04 12:43:44 +00:00
|
|
|
|
2020-03-21 12:39:20 +00:00
|
|
|
Status = IoCreateDevice(FdoExt->DriverObject,
|
|
|
|
sizeof(ISAPNP_PDO_EXTENSION),
|
|
|
|
NULL,
|
|
|
|
FILE_DEVICE_CONTROLLER,
|
2021-10-07 18:53:38 +00:00
|
|
|
FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
|
2020-03-21 12:39:20 +00:00
|
|
|
FALSE,
|
2021-03-04 12:42:42 +00:00
|
|
|
&FdoExt->ReadPortPdo);
|
2020-03-21 12:39:20 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
|
|
|
PdoExt = FdoExt->ReadPortPdo->DeviceExtension;
|
2020-03-21 12:39:20 +00:00
|
|
|
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
|
2021-03-04 12:48:43 +00:00
|
|
|
PdoExt->Common.Signature = IsaPnpReadDataPort;
|
2021-03-04 12:42:42 +00:00
|
|
|
PdoExt->Common.Self = FdoExt->ReadPortPdo;
|
2020-03-21 12:39:20 +00:00
|
|
|
PdoExt->Common.State = dsStopped;
|
|
|
|
PdoExt->FdoExt = FdoExt;
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
IsaPnpRemoveReadPortDO(
|
|
|
|
_In_ PDEVICE_OBJECT Pdo)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
DPRINT("Removing Read Port\n");
|
|
|
|
|
|
|
|
IoDeleteDevice(Pdo);
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
IsaPnpFillDeviceRelations(
|
|
|
|
_In_ PISAPNP_FDO_EXTENSION FdoExt,
|
|
|
|
_Inout_ PIRP Irp,
|
|
|
|
_In_ BOOLEAN IncludeDataPort)
|
|
|
|
{
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PISAPNP_LOGICAL_DEVICE IsaDevice;
|
|
|
|
PDEVICE_RELATIONS DeviceRelations;
|
|
|
|
ULONG PdoCount, i = 0;
|
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
IsaPnpAcquireBusDataLock();
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
/* Try to claim the Read Port for our FDO */
|
|
|
|
if (!ReadPortCreated)
|
|
|
|
{
|
|
|
|
Status = IsaPnpCreateReadPortDO(FdoExt);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
ReadPortCreated = TRUE;
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
IsaPnpReleaseBusDataLock();
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
/* Inactive ISA bus */
|
|
|
|
if (!FdoExt->ReadPortPdo)
|
|
|
|
IncludeDataPort = FALSE;
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
IsaPnpAcquireDeviceDataLock(FdoExt);
|
|
|
|
|
|
|
|
/* If called from the FDO dispatch routine && Active bus */
|
|
|
|
if (IncludeDataPort && FdoExt->ReadPortPdo)
|
|
|
|
{
|
|
|
|
PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension;
|
|
|
|
|
|
|
|
if ((ReadPortExt->Flags & ISAPNP_READ_PORT_ALLOW_FDO_SCAN) &&
|
|
|
|
!(ReadPortExt->Flags & ISAPNP_SCANNED_BY_READ_PORT))
|
|
|
|
{
|
|
|
|
DPRINT("Rescan ISA PnP bus\n");
|
|
|
|
|
|
|
|
/* Run the isolation protocol */
|
2021-03-20 14:50:34 +00:00
|
|
|
FdoExt->Cards = IsaHwTryReadDataPort(FdoExt->ReadDataPort);
|
|
|
|
|
|
|
|
/* Card identification */
|
|
|
|
if (FdoExt->Cards > 0)
|
2021-03-04 12:48:43 +00:00
|
|
|
(VOID)IsaHwFillDeviceList(FdoExt);
|
2021-03-20 14:52:40 +00:00
|
|
|
|
|
|
|
IsaHwWaitForKey();
|
2021-03-04 12:48:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT;
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
PdoCount = FdoExt->DeviceCount;
|
|
|
|
if (IncludeDataPort)
|
|
|
|
++PdoCount;
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
CurrentEntry = FdoExt->DeviceListHead.Flink;
|
|
|
|
while (CurrentEntry != &FdoExt->DeviceListHead)
|
|
|
|
{
|
|
|
|
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
|
|
|
|
|
|
|
|
if (!(IsaDevice->Flags & ISAPNP_PRESENT))
|
|
|
|
--PdoCount;
|
|
|
|
|
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
DeviceRelations = ExAllocatePoolWithTag(PagedPool,
|
|
|
|
FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]),
|
|
|
|
TAG_ISAPNP);
|
|
|
|
if (!DeviceRelations)
|
|
|
|
{
|
2021-03-04 12:48:43 +00:00
|
|
|
IsaPnpReleaseDeviceDataLock(FdoExt);
|
2021-03-04 12:45:38 +00:00
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IncludeDataPort)
|
|
|
|
{
|
2021-03-04 12:48:43 +00:00
|
|
|
PISAPNP_PDO_EXTENSION ReadPortExt = FdoExt->ReadPortPdo->DeviceExtension;
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo;
|
|
|
|
ObReferenceObject(FdoExt->ReadPortPdo);
|
2021-03-04 12:48:43 +00:00
|
|
|
|
|
|
|
/* The Read Port PDO can only be removed by FDO */
|
|
|
|
ReadPortExt->Flags |= ISAPNP_ENUMERATED;
|
2021-03-04 12:45:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CurrentEntry = FdoExt->DeviceListHead.Flink;
|
|
|
|
while (CurrentEntry != &FdoExt->DeviceListHead)
|
|
|
|
{
|
|
|
|
PISAPNP_PDO_EXTENSION PdoExt;
|
|
|
|
|
|
|
|
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
if (!(IsaDevice->Flags & ISAPNP_PRESENT))
|
|
|
|
goto SkipPdo;
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
if (!IsaDevice->Pdo)
|
|
|
|
{
|
|
|
|
Status = IoCreateDevice(FdoExt->DriverObject,
|
|
|
|
sizeof(ISAPNP_PDO_EXTENSION),
|
|
|
|
NULL,
|
|
|
|
FILE_DEVICE_CONTROLLER,
|
|
|
|
FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
|
|
|
|
FALSE,
|
|
|
|
&IsaDevice->Pdo);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2021-03-04 12:48:43 +00:00
|
|
|
goto SkipPdo;
|
2021-03-04 12:45:38 +00:00
|
|
|
|
|
|
|
IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
2021-03-04 12:48:43 +00:00
|
|
|
/* The power pagable flag is always unset */
|
2021-03-04 12:45:38 +00:00
|
|
|
|
|
|
|
PdoExt = IsaDevice->Pdo->DeviceExtension;
|
|
|
|
|
|
|
|
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
|
2021-03-04 12:48:43 +00:00
|
|
|
PdoExt->Common.Signature = IsaPnpLogicalDevice;
|
2021-03-04 12:45:38 +00:00
|
|
|
PdoExt->Common.Self = IsaDevice->Pdo;
|
|
|
|
PdoExt->Common.State = dsStopped;
|
|
|
|
PdoExt->IsaPnpDevice = IsaDevice;
|
|
|
|
PdoExt->FdoExt = FdoExt;
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
if (!NT_SUCCESS(IsaPnpCreateLogicalDeviceRequirements(PdoExt)) ||
|
|
|
|
!NT_SUCCESS(IsaPnpCreateLogicalDeviceResources(PdoExt)))
|
2021-03-04 12:45:38 +00:00
|
|
|
{
|
2021-03-04 12:48:43 +00:00
|
|
|
if (PdoExt->RequirementsList)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
|
|
|
|
PdoExt->RequirementsList = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PdoExt->ResourceList)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
|
|
|
|
PdoExt->ResourceList = NULL;
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
IoDeleteDevice(IsaDevice->Pdo);
|
|
|
|
IsaDevice->Pdo = NULL;
|
2021-03-04 12:48:43 +00:00
|
|
|
goto SkipPdo;
|
2021-03-04 12:45:38 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-04 12:48:43 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
PdoExt = IsaDevice->Pdo->DeviceExtension;
|
|
|
|
}
|
2021-03-04 12:45:38 +00:00
|
|
|
DeviceRelations->Objects[i++] = IsaDevice->Pdo;
|
|
|
|
ObReferenceObject(IsaDevice->Pdo);
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
PdoExt->Flags |= ISAPNP_ENUMERATED;
|
|
|
|
|
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
SkipPdo:
|
|
|
|
if (IsaDevice->Pdo)
|
|
|
|
{
|
|
|
|
PdoExt = IsaDevice->Pdo->DeviceExtension;
|
|
|
|
|
|
|
|
if (PdoExt)
|
|
|
|
PdoExt->Flags &= ~ISAPNP_ENUMERATED;
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
IsaPnpReleaseDeviceDataLock(FdoExt);
|
|
|
|
|
2021-03-04 12:45:38 +00:00
|
|
|
DeviceRelations->Count = i;
|
|
|
|
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
2020-03-21 16:37:45 +00:00
|
|
|
|
2020-03-21 12:39:20 +00:00
|
|
|
return Status;
|
2020-03-16 18:24:07 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
static CODE_SEG("PAGE") DRIVER_ADD_DEVICE IsaAddDevice;
|
|
|
|
|
2010-04-07 20:19:29 +00:00
|
|
|
static
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("PAGE")
|
2010-04-07 20:19:29 +00:00
|
|
|
NTSTATUS
|
2008-11-30 11:16:55 +00:00
|
|
|
NTAPI
|
2010-04-07 20:19:29 +00:00
|
|
|
IsaAddDevice(
|
2021-03-04 12:42:42 +00:00
|
|
|
_In_ PDRIVER_OBJECT DriverObject,
|
|
|
|
_In_ PDEVICE_OBJECT PhysicalDeviceObject)
|
2001-05-01 23:00:05 +00:00
|
|
|
{
|
2020-03-20 18:19:30 +00:00
|
|
|
PDEVICE_OBJECT Fdo;
|
|
|
|
PISAPNP_FDO_EXTENSION FdoExt;
|
|
|
|
NTSTATUS Status;
|
2021-03-04 12:47:34 +00:00
|
|
|
static ULONG BusNumber = 0;
|
2020-03-20 18:19:30 +00:00
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
DPRINT("%s(%p, %p)\n", __FUNCTION__, DriverObject, PhysicalDeviceObject);
|
|
|
|
|
|
|
|
Status = IoCreateDevice(DriverObject,
|
|
|
|
sizeof(*FdoExt),
|
|
|
|
NULL,
|
|
|
|
FILE_DEVICE_BUS_EXTENDER,
|
|
|
|
FILE_DEVICE_SECURE_OPEN,
|
2021-03-04 12:48:43 +00:00
|
|
|
FALSE,
|
2020-03-20 18:19:30 +00:00
|
|
|
&Fdo);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2021-03-04 12:42:42 +00:00
|
|
|
DPRINT1("Failed to create FDO (0x%08lx)\n", Status);
|
2020-03-20 18:19:30 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
FdoExt = Fdo->DeviceExtension;
|
|
|
|
RtlZeroMemory(FdoExt, sizeof(*FdoExt));
|
|
|
|
|
|
|
|
FdoExt->Common.Self = Fdo;
|
2021-03-04 12:48:43 +00:00
|
|
|
FdoExt->Common.Signature = IsaPnpBus;
|
2020-03-20 18:19:30 +00:00
|
|
|
FdoExt->Common.State = dsStopped;
|
|
|
|
FdoExt->DriverObject = DriverObject;
|
2021-03-04 12:47:34 +00:00
|
|
|
FdoExt->BusNumber = BusNumber++;
|
2020-03-20 18:19:30 +00:00
|
|
|
FdoExt->Pdo = PhysicalDeviceObject;
|
|
|
|
FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
|
|
|
|
PhysicalDeviceObject);
|
2021-03-04 12:48:43 +00:00
|
|
|
if (!FdoExt->Ldo)
|
|
|
|
{
|
|
|
|
IoDeleteDevice(Fdo);
|
|
|
|
return STATUS_DEVICE_REMOVED;
|
|
|
|
}
|
2020-03-20 18:19:30 +00:00
|
|
|
|
|
|
|
InitializeListHead(&FdoExt->DeviceListHead);
|
2021-03-04 12:43:44 +00:00
|
|
|
KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE);
|
2020-03-20 18:19:30 +00:00
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
IsaPnpAcquireBusDataLock();
|
|
|
|
InsertTailList(&BusListHead, &FdoExt->BusLink);
|
|
|
|
IsaPnpReleaseBusDataLock();
|
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2001-05-01 23:00:05 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 12:42:42 +00:00
|
|
|
_Dispatch_type_(IRP_MJ_POWER)
|
2021-03-04 12:43:44 +00:00
|
|
|
static DRIVER_DISPATCH_RAISED IsaPower;
|
2021-03-04 12:42:42 +00:00
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
static
|
2020-07-12 13:37:20 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPower(
|
2021-03-04 12:42:42 +00:00
|
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
|
|
_Inout_ PIRP Irp)
|
2020-07-12 13:37:20 +00:00
|
|
|
{
|
|
|
|
PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
if (DevExt->Signature != IsaPnpBus)
|
2020-07-12 13:37:20 +00:00
|
|
|
{
|
2021-03-04 12:48:43 +00:00
|
|
|
switch (IoGetCurrentIrpStackLocation(Irp)->MinorFunction)
|
|
|
|
{
|
|
|
|
case IRP_MN_SET_POWER:
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
PoStartNextPowerIrp(Irp);
|
2020-07-12 13:37:20 +00:00
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return PoCallDriver(((PISAPNP_FDO_EXTENSION)DevExt)->Ldo, Irp);
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:42:42 +00:00
|
|
|
_Dispatch_type_(IRP_MJ_PNP)
|
2021-03-04 12:43:44 +00:00
|
|
|
static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaPnp;
|
2013-05-09 14:06:21 +00:00
|
|
|
|
2010-04-07 20:19:29 +00:00
|
|
|
static
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("PAGE")
|
2010-04-07 20:19:29 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaPnp(
|
2021-03-04 12:42:42 +00:00
|
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
|
|
_Inout_ PIRP Irp)
|
2010-04-07 20:19:29 +00:00
|
|
|
{
|
2020-03-20 18:19:30 +00:00
|
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
PISAPNP_COMMON_EXTENSION DevExt = DeviceObject->DeviceExtension;
|
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
if (DevExt->Signature == IsaPnpBus)
|
2021-03-04 12:42:42 +00:00
|
|
|
return IsaFdoPnp((PISAPNP_FDO_EXTENSION)DevExt, Irp, IrpSp);
|
2020-03-20 18:19:30 +00:00
|
|
|
else
|
2021-03-04 12:42:42 +00:00
|
|
|
return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt, Irp, IrpSp);
|
2010-04-07 20:19:29 +00:00
|
|
|
}
|
2001-05-01 23:00:05 +00:00
|
|
|
|
2024-05-03 13:08:09 +00:00
|
|
|
_Dispatch_type_(IRP_MJ_CREATE)
|
|
|
|
_Dispatch_type_(IRP_MJ_CLOSE)
|
|
|
|
static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaCreateClose;
|
|
|
|
|
|
|
|
static
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaCreateClose(
|
|
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
|
|
_Inout_ PIRP Irp)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
DPRINT("%s(%p, %p)\n", __FUNCTION__, DeviceObject, Irp);
|
|
|
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
|
|
|
|
_Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
|
|
|
|
static CODE_SEG("PAGE") DRIVER_DISPATCH_PAGED IsaForwardOrIgnore;
|
|
|
|
|
|
|
|
static
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IsaForwardOrIgnore(
|
|
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
|
|
_Inout_ PIRP Irp)
|
|
|
|
{
|
|
|
|
PISAPNP_COMMON_EXTENSION CommonExt = DeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
DPRINT("%s(%p, %p) Minor - %X\n", __FUNCTION__, DeviceObject, Irp,
|
|
|
|
IoGetCurrentIrpStackLocation(Irp)->MinorFunction);
|
|
|
|
|
|
|
|
if (CommonExt->Signature == IsaPnpBus)
|
|
|
|
{
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return IoCallDriver(((PISAPNP_FDO_EXTENSION)CommonExt)->Ldo, Irp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NTSTATUS Status = Irp->IoStatus.Status;
|
|
|
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-04 12:43:44 +00:00
|
|
|
CODE_SEG("INIT")
|
2001-05-01 23:00:05 +00:00
|
|
|
NTSTATUS
|
2008-11-30 11:16:55 +00:00
|
|
|
NTAPI
|
2001-05-01 23:00:05 +00:00
|
|
|
DriverEntry(
|
2021-03-04 12:42:42 +00:00
|
|
|
_In_ PDRIVER_OBJECT DriverObject,
|
|
|
|
_In_ PUNICODE_STRING RegistryPath)
|
2001-05-01 23:00:05 +00:00
|
|
|
{
|
2020-03-20 18:19:30 +00:00
|
|
|
DPRINT("%s(%p, %wZ)\n", __FUNCTION__, DriverObject, RegistryPath);
|
2001-05-01 23:00:05 +00:00
|
|
|
|
2024-10-07 14:10:08 +00:00
|
|
|
if (IsNEC_98)
|
|
|
|
{
|
|
|
|
IsaConfigPorts[0] = ISAPNP_WRITE_DATA_PC98;
|
|
|
|
IsaConfigPorts[1] = ISAPNP_ADDRESS_PC98;
|
|
|
|
}
|
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = IsaCreateClose;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = IsaCreateClose;
|
2021-03-04 12:48:43 +00:00
|
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IsaForwardOrIgnore;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IsaForwardOrIgnore;
|
2020-03-20 18:19:30 +00:00
|
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = IsaPnp;
|
2020-07-12 13:37:20 +00:00
|
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = IsaPower;
|
2020-03-20 18:19:30 +00:00
|
|
|
DriverObject->DriverExtension->AddDevice = IsaAddDevice;
|
2001-05-01 23:00:05 +00:00
|
|
|
|
2021-03-04 12:48:43 +00:00
|
|
|
/* FIXME: Fix SDK headers */
|
|
|
|
#if 0
|
|
|
|
_No_competing_thread_begin_
|
|
|
|
#endif
|
|
|
|
|
|
|
|
KeInitializeEvent(&BusSyncEvent, SynchronizationEvent, TRUE);
|
|
|
|
InitializeListHead(&BusListHead);
|
|
|
|
|
|
|
|
/* FIXME: Fix SDK headers */
|
|
|
|
#if 0
|
|
|
|
_No_competing_thread_end_
|
|
|
|
#endif
|
|
|
|
|
2020-03-20 18:19:30 +00:00
|
|
|
return STATUS_SUCCESS;
|
2001-05-01 23:00:05 +00:00
|
|
|
}
|
|
|
|
|
2024-05-03 13:09:23 +00:00
|
|
|
#endif /* UNIT_TEST */
|
|
|
|
|
2001-05-01 23:00:05 +00:00
|
|
|
/* EOF */
|