https://git.reactos.org/?p=reactos.git;a=commitdiff;h=67141abef193080faa7a5…
commit 67141abef193080faa7a59ee096844a2f56f828d
Author: Hervé Poussineau <hpoussin(a)reactos.org>
AuthorDate: Sun Mar 22 14:20:52 2020 +0100
Commit: Hervé Poussineau <hpoussin(a)reactos.org>
CommitDate: Sun Mar 22 14:29:38 2020 +0100
[ISAPNP] Create requirements and resource lists when detecting a device
---
drivers/bus/isapnp/isapnp.c | 200 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 200 insertions(+)
diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c
index 5c5321b3308..e8862345cc0 100644
--- a/drivers/bus/isapnp/isapnp.c
+++ b/drivers/bus/isapnp/isapnp.c
@@ -3,6 +3,7 @@
* FILE: isapnp.c
* PURPOSE: Driver entry
* PROGRAMMERS: Cameron Gutman (cameron.gutman(a)reactos.org)
+ * Hervé Poussineau
*/
#include <isapnp.h>
@@ -136,6 +137,198 @@ IsaFdoCreateDeviceIDs(
return STATUS_SUCCESS;
}
+static
+NTSTATUS
+NTAPI
+IsaFdoCreateRequirements(
+ IN PISAPNP_PDO_EXTENSION PdoExt)
+{
+ PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
+ RTL_BITMAP IrqBitmap[ARRAYSIZE(LogDev->Irq)];
+ ULONG IrqData[ARRAYSIZE(LogDev->Irq)];
+ ULONG ResourceCount = 0;
+ ULONG ListSize, i, j;
+ BOOLEAN FirstIrq = TRUE;
+ PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+
+ /* Count number of requirements */
+ for (i = 0; i < ARRAYSIZE(LogDev->Io); i++)
+ {
+ if (!LogDev->Io[i].Description.Length)
+ break;
+ ResourceCount++;
+ }
+ for (i = 0; i < ARRAYSIZE(LogDev->Irq); i++)
+ {
+ if (!LogDev->Irq[i].Description.Mask)
+ break;
+ IrqData[i] = LogDev->Irq[i].Description.Mask;
+ RtlInitializeBitMap(&IrqBitmap[i], &IrqData[i], 16);
+ ResourceCount += RtlNumberOfSetBits(&IrqBitmap[i]);
+ if (LogDev->Irq[i].Description.Information & 0x4)
+ {
+ /* Add room for level sensitive */
+ ResourceCount += RtlNumberOfSetBits(&IrqBitmap[i]);
+ }
+ }
+ if (ResourceCount == 0)
+ return STATUS_SUCCESS;
+
+ /* Allocate memory to store requirements */
+ ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
+ + ResourceCount * sizeof(IO_RESOURCE_DESCRIPTOR);
+ RequirementsList = ExAllocatePool(PagedPool, ListSize);
+ if (!RequirementsList)
+ return STATUS_NO_MEMORY;
+
+ RtlZeroMemory(RequirementsList, ListSize);
+ RequirementsList->ListSize = ListSize;
+ RequirementsList->InterfaceType = Isa;
+ RequirementsList->AlternativeLists = 1;
+
+ RequirementsList->List[0].Version = 1;
+ RequirementsList->List[0].Revision = 1;
+ RequirementsList->List[0].Count = ResourceCount;
+
+ /* Store requirements */
+ Descriptor = RequirementsList->List[0].Descriptors;
+ for (i = 0; i < ARRAYSIZE(LogDev->Io); i++)
+ {
+ if (!LogDev->Io[i].Description.Length)
+ break;
+ DPRINT("Device.Io[%d].Information = 0x%02x\n", i,
LogDev->Io[i].Description.Information);
+ DPRINT("Device.Io[%d].Minimum = 0x%02x\n", i,
LogDev->Io[i].Description.Minimum);
+ DPRINT("Device.Io[%d].Maximum = 0x%02x\n", i,
LogDev->Io[i].Description.Maximum);
+ DPRINT("Device.Io[%d].Alignment = 0x%02x\n", i,
LogDev->Io[i].Description.Alignment);
+ DPRINT("Device.Io[%d].Length = 0x%02x\n", i,
LogDev->Io[i].Description.Length);
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (LogDev->Io[i].Description.Information & 0x1)
+ Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
+ else
+ Descriptor->Flags = CM_RESOURCE_PORT_10_BIT_DECODE;
+ Descriptor->u.Port.Length = LogDev->Io[i].Description.Length;
+ Descriptor->u.Port.Alignment = LogDev->Io[i].Description.Alignment;
+ Descriptor->u.Port.MinimumAddress.LowPart =
LogDev->Io[i].Description.Minimum;
+ Descriptor->u.Port.MaximumAddress.LowPart =
LogDev->Io[i].Description.Maximum + LogDev->Io[i].Description.Length - 1;
+ Descriptor++;
+ }
+ for (i = 0; i < ARRAYSIZE(LogDev->Irq); i++)
+ {
+ if (!LogDev->Irq[i].Description.Mask)
+ break;
+ DPRINT("Device.Irq[%d].Mask = 0x%02x\n", i,
LogDev->Irq[i].Description.Mask);
+ DPRINT("Device.Irq[%d].Information = 0x%02x\n", i,
LogDev->Irq[i].Description.Information);
+ for (j = 0; j < 15; j++)
+ {
+ if (!RtlCheckBit(&IrqBitmap[i], j))
+ continue;
+ if (FirstIrq)
+ FirstIrq = FALSE;
+ else
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ Descriptor->u.Interrupt.MinimumVector =
Descriptor->u.Interrupt.MaximumVector = j;
+ Descriptor++;
+ if (LogDev->Irq[i].Description.Information & 0x4)
+ {
+ /* Level interrupt */
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->u.Interrupt.MinimumVector =
Descriptor->u.Interrupt.MaximumVector = j;
+ Descriptor++;
+ }
+ }
+ }
+
+ PdoExt->RequirementsList = RequirementsList;
+ return STATUS_SUCCESS;
+}
+
+static
+NTSTATUS
+NTAPI
+IsaFdoCreateResources(
+ IN PISAPNP_PDO_EXTENSION PdoExt)
+{
+ PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
+ ULONG ResourceCount = 0;
+ ULONG ListSize, i;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+
+ /* Count number of required resources */
+ for (i = 0; i < ARRAYSIZE(LogDev->Io); i++)
+ {
+ if (LogDev->Io[i].CurrentBase)
+ ResourceCount++;
+ else
+ break;
+ }
+ for (i = 0; i < ARRAYSIZE(LogDev->Irq); i++)
+ {
+ if (LogDev->Irq[i].CurrentNo)
+ ResourceCount++;
+ else
+ break;
+ }
+ if (ResourceCount == 0)
+ return STATUS_SUCCESS;
+
+ /* Allocate memory to store resources */
+ ListSize = sizeof(CM_RESOURCE_LIST)
+ + (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+ ResourceList = ExAllocatePool(PagedPool, ListSize);
+ if (!ResourceList)
+ return STATUS_NO_MEMORY;
+
+ RtlZeroMemory(ResourceList, ListSize);
+ 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;
+ for (i = 0; i < ARRAYSIZE(LogDev->Io); i++)
+ {
+ if (!LogDev->Io[i].CurrentBase)
+ continue;
+ Descriptor =
&ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ if (LogDev->Io[i].Description.Information & 0x1)
+ Descriptor->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
+ else
+ Descriptor->Flags = CM_RESOURCE_PORT_10_BIT_DECODE;
+ Descriptor->u.Port.Length = LogDev->Io[i].Description.Length;
+ Descriptor->u.Port.Start.LowPart = LogDev->Io[i].CurrentBase;
+ }
+ for (i = 0; i < ARRAYSIZE(LogDev->Irq); i++)
+ {
+ if (!LogDev->Irq[i].CurrentNo)
+ continue;
+ 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;
+ Descriptor->u.Interrupt.Affinity = -1;
+ }
+
+ PdoExt->ResourceList = ResourceList;
+ PdoExt->ResourceListSize = ListSize;
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
NTAPI
IsaPnpFillDeviceRelations(
@@ -197,6 +390,13 @@ IsaPnpFillDeviceRelations(
PdoExt->FdoExt = FdoExt;
Status = IsaFdoCreateDeviceIDs(PdoExt);
+
+ if (NT_SUCCESS(Status))
+ Status = IsaFdoCreateRequirements(PdoExt);
+
+ if (NT_SUCCESS(Status))
+ Status = IsaFdoCreateResources(PdoExt);
+
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(IsaDevice->Pdo);