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

commit 3f5aeb93638a4ec2592ebd6b4d4be319bc8b510b
Author: Eric Kohl <eric.k...@reactos.org>
AuthorDate: Sun Oct 15 15:21:56 2017 +0200

    [STORPORT] Attach copies of the resource lists to the FDO device extension 
and use them to fill the access ranges in the port configuration.
    Storahci does not crash on initialization any more. :-)
    CORE-13866
---
 drivers/storage/port/storport/fdo.c      |  19 ++++
 drivers/storage/port/storport/miniport.c | 151 ++++++++++++++++++++++++++++++-
 drivers/storage/port/storport/misc.c     |  72 +++++++++++++++
 drivers/storage/port/storport/precomp.h  |   9 ++
 4 files changed, 250 insertions(+), 1 deletion(-)

diff --git a/drivers/storage/port/storport/fdo.c 
b/drivers/storage/port/storport/fdo.c
index cb85d65c77..3f569ac5c9 100644
--- a/drivers/storage/port/storport/fdo.c
+++ b/drivers/storage/port/storport/fdo.c
@@ -74,6 +74,7 @@ PortFdoStartDevice(
     _In_ PFDO_DEVICE_EXTENSION DeviceExtension,
     _In_ PIRP Irp)
 {
+    PIO_STACK_LOCATION Stack;
     NTSTATUS Status;
 
     DPRINT1("PortFdoStartDevice(%p %p)\n",
@@ -81,6 +82,9 @@ PortFdoStartDevice(
 
     ASSERT(DeviceExtension->ExtensionType == FdoExtension);
 
+    /* Get the current stack location */
+    Stack = IoGetCurrentIrpStackLocation(Irp);
+
     /* Start the lower device if the FDO is in 'stopped' state */
     if (DeviceExtension->PnpState == dsStopped)
     {
@@ -95,6 +99,21 @@ PortFdoStartDevice(
     /* Change to the 'started' state */
     DeviceExtension->PnpState = dsStarted;
 
+    /* Copy the raw and translated resource lists into the device extension */
+    if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
+        Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
+    {
+        DeviceExtension->AllocatedResources = CopyResourceList(NonPagedPool,
+                                                               
Stack->Parameters.StartDevice.AllocatedResources);
+        if (DeviceExtension->AllocatedResources == NULL)
+            return STATUS_NO_MEMORY;
+
+        DeviceExtension->TranslatedResources = CopyResourceList(NonPagedPool,
+                                                                
Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
+        if (DeviceExtension->TranslatedResources == NULL)
+            return STATUS_NO_MEMORY;
+    }
+
     /* Start the miniport (FindAdapter & Initialize) */
     Status = PortFdoStartMiniport(DeviceExtension);
     if (!NT_SUCCESS(Status))
diff --git a/drivers/storage/port/storport/miniport.c 
b/drivers/storage/port/storport/miniport.c
index dc4818dbd2..852ef426a4 100644
--- a/drivers/storage/port/storport/miniport.c
+++ b/drivers/storage/port/storport/miniport.c
@@ -89,6 +89,147 @@ InitializeConfiguration(
 }
 
 
+static
+VOID
+AssignResourcesToConfiguration(
+    _In_ PPORT_CONFIGURATION_INFORMATION PortConfiguration,
+    _In_ PCM_RESOURCE_LIST ResourceList,
+    _In_ ULONG NumberOfAccessRanges)
+{
+    PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
+    PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
+    PACCESS_RANGE AccessRange;
+    INT i, j;
+    ULONG RangeNumber = 0, Interrupt = 0, Dma = 0;
+
+    DPRINT1("AssignResourceToConfiguration(%p %p %lu)\n",
+            PortConfiguration, ResourceList, NumberOfAccessRanges);
+
+    FullDescriptor = &ResourceList->List[0];
+    for (i = 0; i < ResourceList->Count; i++)
+    {
+        PartialResourceList = &FullDescriptor->PartialResourceList;
+
+        for (j = 0; j < PartialResourceList->Count; j++)
+        {
+            PartialDescriptor = &PartialResourceList->PartialDescriptors[j];
+
+            switch (PartialDescriptor->Type)
+            {
+                case CmResourceTypePort:
+                    DPRINT1("Port: 0x%I64x (0x%lx)\n",
+                            PartialDescriptor->u.Port.Start.QuadPart,
+                            PartialDescriptor->u.Port.Length);
+                    if (RangeNumber < NumberOfAccessRanges)
+                    {
+                        AccessRange = 
&((*(PortConfiguration->AccessRanges))[RangeNumber]);
+                        AccessRange->RangeStart = 
PartialDescriptor->u.Port.Start;
+                        AccessRange->RangeLength = 
PartialDescriptor->u.Port.Length;
+                        AccessRange->RangeInMemory = FALSE;
+                        RangeNumber++;
+                    }
+                    break;
+
+                case CmResourceTypeMemory:
+                    DPRINT1("Memory: 0x%I64x (0x%lx)\n",
+                            PartialDescriptor->u.Memory.Start.QuadPart,
+                            PartialDescriptor->u.Memory.Length);
+                    if (RangeNumber < NumberOfAccessRanges)
+                    {
+                        AccessRange = 
&((*(PortConfiguration->AccessRanges))[RangeNumber]);
+                        AccessRange->RangeStart = 
PartialDescriptor->u.Memory.Start;
+                        AccessRange->RangeLength = 
PartialDescriptor->u.Memory.Length;
+                        AccessRange->RangeInMemory = TRUE;
+                        RangeNumber++;
+                    }
+                    break;
+
+                case CmResourceTypeInterrupt:
+                    DPRINT1("Interrupt: Level %lu  Vector %lu\n",
+                            PartialDescriptor->u.Interrupt.Level,
+                            PartialDescriptor->u.Interrupt.Vector);
+                    if (Interrupt == 0)
+                    {
+                        /* Copy interrupt data */
+                        PortConfiguration->BusInterruptLevel = 
PartialDescriptor->u.Interrupt.Level;
+                        PortConfiguration->BusInterruptVector = 
PartialDescriptor->u.Interrupt.Vector;
+
+                        /* Set interrupt mode accordingly to the resource */
+                        if (PartialDescriptor->Flags == 
CM_RESOURCE_INTERRUPT_LATCHED)
+                        {
+                            PortConfiguration->InterruptMode = Latched;
+                        }
+                        else if (PartialDescriptor->Flags == 
CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
+                        {
+                            PortConfiguration->InterruptMode = LevelSensitive;
+                        }
+                    }
+                    else if (Interrupt == 1)
+                    {
+                        /* Copy interrupt data */
+                        PortConfiguration->BusInterruptLevel2 = 
PartialDescriptor->u.Interrupt.Level;
+                        PortConfiguration->BusInterruptVector2 = 
PartialDescriptor->u.Interrupt.Vector;
+
+                        /* Set interrupt mode accordingly to the resource */
+                        if (PartialDescriptor->Flags == 
CM_RESOURCE_INTERRUPT_LATCHED)
+                        {
+                            PortConfiguration->InterruptMode2 = Latched;
+                        }
+                        else if (PartialDescriptor->Flags == 
CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
+                        {
+                            PortConfiguration->InterruptMode2 = LevelSensitive;
+                        }
+                    }
+                    Interrupt++;
+                    break;
+
+                case CmResourceTypeDma:
+                    DPRINT1("Dma: Channel: %lu  Port: %lu\n",
+                            PartialDescriptor->u.Dma.Channel,
+                            PartialDescriptor->u.Dma.Port);
+                    if (Dma == 0)
+                    {
+                        PortConfiguration->DmaChannel = 
PartialDescriptor->u.Dma.Channel;
+                        PortConfiguration->DmaPort = 
PartialDescriptor->u.Dma.Port;
+
+                        if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8)
+                            PortConfiguration->DmaWidth = Width8Bits;
+                        else if ((PartialDescriptor->Flags & 
CM_RESOURCE_DMA_16) ||
+                                 (PartialDescriptor->Flags & 
CM_RESOURCE_DMA_8_AND_16))
+                            PortConfiguration->DmaWidth = Width16Bits;
+                        else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32)
+                            PortConfiguration->DmaWidth = Width32Bits;
+                    }
+                    else if (Dma == 1)
+                    {
+                        PortConfiguration->DmaChannel2 = 
PartialDescriptor->u.Dma.Channel;
+                        PortConfiguration->DmaPort2 = 
PartialDescriptor->u.Dma.Port;
+
+                        if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8)
+                            PortConfiguration->DmaWidth2 = Width8Bits;
+                        else if ((PartialDescriptor->Flags & 
CM_RESOURCE_DMA_16) ||
+                                 (PartialDescriptor->Flags & 
CM_RESOURCE_DMA_8_AND_16))
+                            PortConfiguration->DmaWidth2 = Width16Bits;
+                        else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32)
+                            PortConfiguration->DmaWidth2 = Width32Bits;
+                    }
+                    Dma++;
+                    break;
+
+                default:
+                    DPRINT1("Other: %u\n", PartialDescriptor->Type);
+                    break;
+            }
+        }
+
+        /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
+        FullDescriptor = 
(PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptor->PartialResourceList.PartialDescriptors
 + 
+                                                        
FullDescriptor->PartialResourceList.Count);
+    }
+}
+
+
 NTSTATUS
 MiniportInitialize(
     _In_ PMINIPORT Miniport,
@@ -126,8 +267,15 @@ MiniportInitialize(
                                      InitData,
                                      DeviceExtension->BusNumber,
                                      DeviceExtension->SlotNumber);
+    if (!NT_SUCCESS(Status))
+        return Status;
 
-    return Status;
+    /* Assign the resources to the port configuration */
+    AssignResourcesToConfiguration(&Miniport->PortConfig,
+                                   DeviceExtension->AllocatedResources,
+                                   InitData->NumberOfAccessRanges);
+
+    return STATUS_SUCCESS;
 }
 
 
@@ -150,6 +298,7 @@ MiniportFindAdapter(
                                                &Reserved);
     DPRINT1("HwFindAdapter() returned %lu\n", Result);
 
+    /* Convert the result to a status code */
     switch (Result)
     {
         case SP_RETURN_NOT_FOUND:
diff --git a/drivers/storage/port/storport/misc.c 
b/drivers/storage/port/storport/misc.c
index 54832c48aa..5f42be2fe8 100644
--- a/drivers/storage/port/storport/misc.c
+++ b/drivers/storage/port/storport/misc.c
@@ -95,4 +95,76 @@ GetBusInterface(
     return InterfaceTypeUndefined;
 }
 
+
+static
+ULONG
+GetResourceListSize(
+    PCM_RESOURCE_LIST ResourceList)
+{
+    PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+    INT i;
+    ULONG Size;
+
+    DPRINT1("GetResourceListSize(%p)\n", ResourceList);
+
+    Size = sizeof(CM_RESOURCE_LIST);
+    if (ResourceList->Count == 0)
+    {
+        DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
+        return Size;
+    }
+
+    DPRINT1("ResourceList->Count: %lu\n", ResourceList->Count);
+
+    Descriptor = &ResourceList->List[0];
+    for (i = 0; i < ResourceList->Count; i++)
+    {
+        /* Process resources in CM_FULL_RESOURCE_DESCRIPTOR block number ix. */
+
+        DPRINT1("PartialResourceList->Count: %lu\n", 
Descriptor->PartialResourceList.Count);
+
+        /* Add the size of the current full descriptor */
+        Size += sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 
+                (Descriptor->PartialResourceList.Count - 1) * 
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+        /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
+        Descriptor = 
(PCM_FULL_RESOURCE_DESCRIPTOR)(Descriptor->PartialResourceList.PartialDescriptors
 + 
+                                                    
Descriptor->PartialResourceList.Count);
+    }
+
+    DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
+    return Size;
+}
+
+
+PCM_RESOURCE_LIST
+CopyResourceList(
+    POOL_TYPE PoolType,
+    PCM_RESOURCE_LIST Source)
+{
+    PCM_RESOURCE_LIST Destination;
+    ULONG Size;
+
+    DPRINT1("CopyResourceList(%lu %p)\n",
+            PoolType, Source);
+
+    /* Get the size of the resource list */
+    Size = GetResourceListSize(Source);
+
+    /* Allocate a new buffer */
+    Destination = ExAllocatePoolWithTag(PoolType,
+                                        Size,
+                                        TAG_RESOURCE_LIST);
+    if (Destination == NULL)
+        return NULL;
+
+    /* Copy the resource list */
+    RtlCopyMemory(Destination,
+                  Source,
+                  Size);
+
+    return Destination;
+}
+
+
 /* EOF */
diff --git a/drivers/storage/port/storport/precomp.h 
b/drivers/storage/port/storport/precomp.h
index b084e0e9da..beacc8eb77 100644
--- a/drivers/storage/port/storport/precomp.h
+++ b/drivers/storage/port/storport/precomp.h
@@ -27,6 +27,7 @@
 #define TAG_INIT_DATA      'DItS'
 #define TAG_MINIPORT_DATA  'DMtS'
 #define TAG_ACCRESS_RANGE  'RAtS'
+#define TAG_RESOURCE_LIST  'LRtS'
 
 typedef enum
 {
@@ -90,6 +91,8 @@ typedef struct _FDO_DEVICE_EXTENSION
     MINIPORT Miniport;
     ULONG BusNumber;
     ULONG SlotNumber;
+    PCM_RESOURCE_LIST AllocatedResources;
+    PCM_RESOURCE_LIST TranslatedResources;
 } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 
@@ -147,6 +150,12 @@ INTERFACE_TYPE
 GetBusInterface(
     PDEVICE_OBJECT DeviceObject);
 
+PCM_RESOURCE_LIST
+CopyResourceList(
+    POOL_TYPE PoolType,
+    PCM_RESOURCE_LIST Source);
+
+
 /* pdo.c */
 
 NTSTATUS

Reply via email to