https://git.reactos.org/?p=reactos.git;a=commitdiff;h=adac7dc2e5847dc7b214622484c6f8ce9fc605ae

commit adac7dc2e5847dc7b214622484c6f8ce9fc605ae
Author:     Dmitry Borisov <[email protected]>
AuthorDate: Sat Mar 20 20:53:54 2021 +0600
Commit:     Dmitry Borisov <[email protected]>
CommitDate: Sun Jun 20 19:24:32 2021 +0600

    [ISAPNP] Implement device configuration
---
 drivers/bus/isapnp/hardware.c | 297 ++++++++++++++++++++++++++++++++++++++++++
 drivers/bus/isapnp/isapnp.h   |   7 +
 drivers/bus/isapnp/isapnphw.h |   7 +
 drivers/bus/isapnp/pdo.c      |  14 +-
 4 files changed, 323 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c
index 188d1732447..26d6b120671 100644
--- a/drivers/bus/isapnp/hardware.c
+++ b/drivers/bus/isapnp/hardware.c
@@ -61,6 +61,30 @@ WriteByte(
     WriteData(Value);
 }
 
+static
+inline
+VOID
+WriteWord(
+    _In_ UCHAR Address,
+    _In_ USHORT Value)
+{
+    WriteAddress(Address + 1);
+    WriteData((UCHAR)Value);
+    WriteAddress(Address);
+    WriteData(Value >> 8);
+}
+
+static
+inline
+VOID
+WriteDoubleWord(
+    _In_ UCHAR Address,
+    _In_ ULONG Value)
+{
+    WriteWord(Address + 2, (USHORT)Value);
+    WriteWord(Address, Value >> 16);
+}
+
 static
 inline
 UCHAR
@@ -1164,6 +1188,175 @@ ReadCurrentResources(
     return TRUE;
 }
 
+static
+CODE_SEG("PAGE")
+VOID
+WriteResources(
+    _In_ PUCHAR ReadDataPort,
+    _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
+    _In_ PCM_PARTIAL_RESOURCE_LIST PartialResourceList)
+{
+    UCHAR i,
+          NumberOfIo = 0,
+          NumberOfIrq = 0,
+          NumberOfDma = 0,
+          NumberOfMemory = 0,
+          NumberOfMemory32 = 0;
+
+    PAGED_CODE();
+
+    WriteLogicalDeviceNumber(LogDevice->LDN);
+
+    for (i = 0; i < PartialResourceList->Count; i++)
+    {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = 
&PartialResourceList->PartialDescriptors[i];
+        UCHAR Index;
+
+        switch (Descriptor->Type)
+        {
+            case CmResourceTypePort:
+            {
+                (VOID)FindIoDescriptor(LogDevice,
+                                       0,
+                                       Descriptor->u.Port.Start.LowPart,
+                                       Descriptor->u.Port.Start.LowPart +
+                                       Descriptor->u.Port.Length - 1,
+                                       NULL,
+                                       NULL,
+                                       &Index);
+
+                WriteWord(ISAPNP_IOBASE(Index), 
(USHORT)Descriptor->u.Port.Start.LowPart);
+
+                ++NumberOfIo;
+                break;
+            }
+
+            case CmResourceTypeInterrupt:
+            {
+                (VOID)FindIrqDescriptor(LogDevice, 
Descriptor->u.Interrupt.Level, &Index);
+
+                WriteByte(ISAPNP_IRQNO(Index), 
(UCHAR)Descriptor->u.Interrupt.Level);
+                WriteByte(ISAPNP_IRQTYPE(Index),
+                          Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED
+                          ? IRQTYPE_HIGH_EDGE : IRQTYPE_LOW_LEVEL);
+
+                ++NumberOfIrq;
+                break;
+            }
+
+            case CmResourceTypeDma:
+            {
+                (VOID)FindDmaDescriptor(LogDevice, Descriptor->u.Dma.Channel, 
&Index);
+
+                WriteByte(ISAPNP_DMACHANNEL(Index), 
(UCHAR)Descriptor->u.Dma.Channel);
+
+                ++NumberOfDma;
+                break;
+            }
+
+            case CmResourceTypeMemory:
+            {
+                BOOLEAN Memory32;
+                UCHAR Information;
+                UCHAR MemoryControl = MEMORY_USE_8_BIT_DECODER;
+
+                (VOID)FindMemoryDescriptor(LogDevice,
+                                           Descriptor->u.Memory.Start.LowPart,
+                                           Descriptor->u.Memory.Start.LowPart +
+                                           Descriptor->u.Memory.Length - 1,
+                                           &Memory32,
+                                           &Information,
+                                           &Index);
+
+                if (!Memory32)
+                {
+                    if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
+                        MemoryControl = MEMORY_USE_16_BIT_DECODER;
+
+                    WriteWord(ISAPNP_MEMBASE(Index),
+                              (USHORT)(Descriptor->u.Memory.Start.LowPart >> 
8));
+
+                    if (ReadMemoryControl(ReadDataPort, Index) & 
MEMORY_UPPER_LIMIT)
+                    {
+                        WriteByte(ISAPNP_MEMCONTROL(Index),
+                                  MemoryControl | MEMORY_UPPER_LIMIT);
+                        WriteWord(ISAPNP_MEMLIMIT(Index),
+                                  (USHORT)((Descriptor->u.Memory.Start.LowPart 
+
+                                            Descriptor->u.Memory.Length) >> 
8));
+                    }
+                    else
+                    {
+                        WriteByte(ISAPNP_MEMCONTROL(Index), MemoryControl);
+                        WriteWord(ISAPNP_MEMLIMIT(Index),
+                                  (USHORT)(LENGTH_TO_RANGE_LENGTH(Descriptor->
+                                                                  
u.Memory.Length) >> 8));
+                    }
+
+                    ++NumberOfMemory;
+                }
+                else
+                {
+                    WriteDoubleWord(ISAPNP_MEMBASE32(Index),
+                                    Descriptor->u.Memory.Start.LowPart);
+
+                    if ((Information & MEMRANGE_16_BIT_MEMORY_MASK) == 
MEMRANGE_32_BIT_MEMORY_ONLY)
+                        MemoryControl = MEMORY_USE_32_BIT_DECODER;
+                    else if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
+                        MemoryControl = MEMORY_USE_16_BIT_DECODER;
+
+                    if (ReadMemoryControl32(ReadDataPort, Index) & 
MEMORY_UPPER_LIMIT)
+                    {
+                        WriteByte(ISAPNP_MEMCONTROL32(Index),
+                                  MemoryControl | MEMORY_UPPER_LIMIT);
+                        WriteDoubleWord(ISAPNP_MEMLIMIT32(Index),
+                                        Descriptor->u.Memory.Start.LowPart +
+                                        Descriptor->u.Memory.Length);
+                    }
+                    else
+                    {
+                        WriteByte(ISAPNP_MEMCONTROL32(Index), MemoryControl);
+                        WriteDoubleWord(ISAPNP_MEMLIMIT32(Index),
+                                        
LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length));
+                    }
+
+                    ++NumberOfMemory32;
+                }
+
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+    for (i = NumberOfIo; i < RTL_NUMBER_OF(LogDevice->Io); i++)
+    {
+        WriteWord(ISAPNP_IOBASE(i), 0);
+    }
+    for (i = NumberOfIrq; i < RTL_NUMBER_OF(LogDevice->Irq); i++)
+    {
+        WriteByte(ISAPNP_IRQNO(i), 0);
+        WriteByte(ISAPNP_IRQTYPE(i), 0);
+    }
+    for (i = NumberOfDma; i < RTL_NUMBER_OF(LogDevice->Dma); i++)
+    {
+        WriteByte(ISAPNP_DMACHANNEL(i), 4);
+    }
+    for (i = NumberOfMemory; i < RTL_NUMBER_OF(LogDevice->MemRange); i++)
+    {
+        WriteWord(ISAPNP_MEMBASE(i), 0);
+        WriteByte(ISAPNP_MEMCONTROL(i), 0);
+        WriteWord(ISAPNP_MEMLIMIT(i), 0);
+    }
+    for (i = NumberOfMemory32; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++)
+    {
+        WriteDoubleWord(ISAPNP_MEMBASE32(i), 0);
+        WriteByte(ISAPNP_MEMCONTROL32(i), 0);
+        WriteDoubleWord(ISAPNP_MEMLIMIT32(i), 0);
+    }
+}
+
 CODE_SEG("PAGE")
 UCHAR
 IsaHwTryReadDataPort(
@@ -1405,6 +1598,110 @@ Deactivate:
     return STATUS_SUCCESS;
 }
 
+CODE_SEG("PAGE")
+NTSTATUS
+IsaHwConfigureDevice(
+    _In_ PISAPNP_FDO_EXTENSION FdoExt,
+    _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice,
+    _In_ PCM_RESOURCE_LIST Resources)
+{
+    UCHAR i,
+          NumberOfIo = 0,
+          NumberOfIrq = 0,
+          NumberOfDma = 0,
+          NumberOfMemory = 0;
+
+    PAGED_CODE();
+
+    if (!Resources)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Validate the resource list */
+    for (i = 0; i < Resources->List[0].PartialResourceList.Count; i++)
+    {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor =
+            &Resources->List[0].PartialResourceList.PartialDescriptors[i];
+
+        switch (Descriptor->Type)
+        {
+            case CmResourceTypePort:
+            {
+                if (++NumberOfIo > RTL_NUMBER_OF(LogicalDevice->Io))
+                    return STATUS_INVALID_PARAMETER_1;
+
+                if (!FindIoDescriptor(LogicalDevice,
+                                      0,
+                                      Descriptor->u.Port.Start.LowPart,
+                                      Descriptor->u.Port.Start.LowPart +
+                                      Descriptor->u.Port.Length - 1,
+                                      NULL,
+                                      NULL,
+                                      NULL))
+                {
+                    return STATUS_RESOURCE_DATA_NOT_FOUND;
+                }
+
+                break;
+            }
+
+            case CmResourceTypeInterrupt:
+            {
+                if (++NumberOfIrq > RTL_NUMBER_OF(LogicalDevice->Irq))
+                    return STATUS_INVALID_PARAMETER_2;
+
+                if (!FindIrqDescriptor(LogicalDevice, 
Descriptor->u.Interrupt.Level, NULL))
+                    return STATUS_RESOURCE_DATA_NOT_FOUND;
+
+                break;
+            }
+
+            case CmResourceTypeDma:
+            {
+                if (++NumberOfDma > RTL_NUMBER_OF(LogicalDevice->Dma))
+                    return STATUS_INVALID_PARAMETER_3;
+
+                if (!FindDmaDescriptor(LogicalDevice, 
Descriptor->u.Dma.Channel, NULL))
+                    return STATUS_RESOURCE_DATA_NOT_FOUND;
+
+                break;
+            }
+
+            case CmResourceTypeMemory:
+            {
+                BOOLEAN Memory32;
+
+                if (++NumberOfMemory > RTL_NUMBER_OF(LogicalDevice->MemRange))
+                    return STATUS_INVALID_PARAMETER_4;
+
+                if (!FindMemoryDescriptor(LogicalDevice,
+                                          Descriptor->u.Memory.Start.LowPart,
+                                          Descriptor->u.Memory.Start.LowPart +
+                                          Descriptor->u.Memory.Length - 1,
+                                          &Memory32,
+                                          NULL,
+                                          NULL))
+                {
+                    return STATUS_RESOURCE_DATA_NOT_FOUND;
+                }
+
+                if (!Memory32 && (Descriptor->u.Memory.Start.LowPart & 0xFF))
+                    return STATUS_INVALID_PARAMETER;
+
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+    WriteResources(FdoExt->ReadDataPort, LogicalDevice, 
&Resources->List[0].PartialResourceList);
+
+    KeStallExecutionProcessor(10000);
+
+    return STATUS_SUCCESS;
+}
+
 _IRQL_requires_max_(DISPATCH_LEVEL)
 VOID
 IsaHwWakeDevice(
diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h
index 19702f36274..ad48008251f 100644
--- a/drivers/bus/isapnp/isapnp.h
+++ b/drivers/bus/isapnp/isapnp.h
@@ -375,6 +375,13 @@ NTSTATUS
 IsaHwFillDeviceList(
     _In_ PISAPNP_FDO_EXTENSION FdoExt);
 
+CODE_SEG("PAGE")
+NTSTATUS
+IsaHwConfigureDevice(
+    _In_ PISAPNP_FDO_EXTENSION FdoExt,
+    _In_ PISAPNP_LOGICAL_DEVICE LogicalDevice,
+    _In_ PCM_RESOURCE_LIST Resources);
+
 _IRQL_requires_max_(DISPATCH_LEVEL)
 VOID
 IsaHwWakeDevice(
diff --git a/drivers/bus/isapnp/isapnphw.h b/drivers/bus/isapnp/isapnphw.h
index c41d6d1b7be..0023aac4fdf 100644
--- a/drivers/bus/isapnp/isapnphw.h
+++ b/drivers/bus/isapnp/isapnphw.h
@@ -31,10 +31,15 @@ extern "C" {
 #define ISAPNP_MEMBASE(n) (0x40 + ((n) * 8))
 #define ISAPNP_MEMCONTROL(n) (0x42 + ((n) * 8))
 #define    MEMORY_UPPER_LIMIT 0x01
+#define    MEMORY_USE_8_BIT_DECODER 0x00
+#define    MEMORY_USE_16_BIT_DECODER 0x02
+#define    MEMORY_USE_32_BIT_DECODER 0x06
 #define ISAPNP_MEMLIMIT(n) (0x43 + ((n) * 8))
 #define ISAPNP_IOBASE(n) (0x60 + ((n)*2))
 #define ISAPNP_IRQNO(n) (0x70 + ((n)*2))
 #define ISAPNP_IRQTYPE(n) (0x71 + ((n) * 2))
+#define    IRQTYPE_LOW_LEVEL 0x01
+#define    IRQTYPE_HIGH_EDGE 0x02
 #define ISAPNP_DMACHANNEL(n) (0x74 + (n))
 #define ISAPNP_MEMBASE32(n) ((n) == 0 ? 0x76 : (0x70 + (n) * 16))
 #define ISAPNP_MEMCONTROL32(n) ((n) == 0 ? 0x7A : (0x74 + (n) * 16))
@@ -63,6 +68,8 @@ extern "C" {
 #define ISAPNP_IS_LARGE_TAG(t) (((t) & 0x80))
 #define ISAPNP_LARGE_TAG_NAME(t) (t)
 #define ISAPNP_TAG_MEMRANGE 0x81
+#define    MEMRANGE_16_BIT_MEMORY_MASK (0x10 | 0x08)
+#define       MEMRANGE_32_BIT_MEMORY_ONLY 0x18
 #define ISAPNP_TAG_ANSISTR 0x82
 #define ISAPNP_TAG_UNICODESTR 0x83
 #define ISAPNP_TAG_MEM32RANGE 0x85
diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c
index 1ee0e51b7ea..f2014ffbc90 100644
--- a/drivers/bus/isapnp/pdo.c
+++ b/drivers/bus/isapnp/pdo.c
@@ -897,9 +897,19 @@ IsaPdoPnp(
             {
                 IsaHwWakeDevice(PdoExt->IsaPnpDevice);
 
-                Status = STATUS_SUCCESS;
+                Status = IsaHwConfigureDevice(PdoExt->FdoExt,
+                                              PdoExt->IsaPnpDevice,
+                                              
IrpSp->Parameters.StartDevice.AllocatedResources);
+                if (NT_SUCCESS(Status))
+                {
+                    IsaHwActivateDevice(PdoExt->FdoExt, PdoExt->IsaPnpDevice);
+                }
+                else
+                {
+                    DPRINT1("Failed to configure CSN %u, LDN %u with status 
0x%08lx\n",
+                            PdoExt->IsaPnpDevice->CSN, 
PdoExt->IsaPnpDevice->LDN, Status);
+                }
 
-                IsaHwActivateDevice(PdoExt->FdoExt, PdoExt->IsaPnpDevice);
                 IsaHwWaitForKey();
             }
             else

Reply via email to