[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
This commit is contained in:
Eric Kohl 2017-10-15 15:21:56 +02:00
parent 6808e7d25b
commit 3f5aeb9363
4 changed files with 250 additions and 1 deletions

View file

@ -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))

View file

@ -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:

View file

@ -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 */

View file

@ -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