diff --git a/drivers/storage/port/storport/fdo.c b/drivers/storage/port/storport/fdo.c index 9072971a91e..3c49619b23e 100644 --- a/drivers/storage/port/storport/fdo.c +++ b/drivers/storage/port/storport/fdo.c @@ -15,6 +15,90 @@ /* FUNCTIONS ******************************************************************/ +static +BOOLEAN +NTAPI +PortFdoInterruptRoutine( + _In_ PKINTERRUPT Interrupt, + _In_ PVOID ServiceContext) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + + DPRINT1("PortFdoInterruptRoutine(%p %p)\n", + Interrupt, ServiceContext); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)ServiceContext; + + return MiniportHwInterrupt(&DeviceExtension->Miniport); +} + + +static +NTSTATUS +PortFdoConnectInterrupt( + _In_ PFDO_DEVICE_EXTENSION DeviceExtension) +{ + ULONG Vector; + KIRQL Irql; + KINTERRUPT_MODE InterruptMode; + BOOLEAN ShareVector; + KAFFINITY Affinity; + NTSTATUS Status; + + DPRINT1("PortFdoConnectInterrupt(%p)\n", + DeviceExtension); + + /* No resources, no interrupt. Done! */ + if (DeviceExtension->AllocatedResources == NULL || + DeviceExtension->TranslatedResources == NULL) + { + DPRINT1("Checkpoint\n"); + return STATUS_SUCCESS; + } + + /* Get the interrupt data from the resource list */ + Status = GetResourceListInterrupt(DeviceExtension, + &Vector, + &Irql, + &InterruptMode, + &ShareVector, + &Affinity); + if (!NT_SUCCESS(Status)) + { + DPRINT1("GetResourceListInterrupt() failed (Status 0x%08lx)\n", Status); + return Status; + } + + DPRINT1("Vector: %lu\n", Vector); + DPRINT1("Irql: %lu\n", Irql); + + DPRINT1("Affinity: 0x%08lx\n", Affinity); + + /* Connect the interrupt */ + Status = IoConnectInterrupt(&DeviceExtension->Interrupt, + PortFdoInterruptRoutine, + DeviceExtension, + NULL, + Vector, + Irql, + Irql, + InterruptMode, + ShareVector, + Affinity, + FALSE); + if (NT_SUCCESS(Status)) + { + DeviceExtension->InterruptIrql = Irql; + } + else + { + DPRINT1("IoConnectInterrupt() failed (Status 0x%08lx)\n", Status); + } + + return Status; +} + + static NTSTATUS PortFdoStartMiniport( @@ -55,6 +139,10 @@ PortFdoStartMiniport( return Status; } + + Status = PortFdoConnectInterrupt(DeviceExtension); + + /* Call the miniports HwInitialize function */ Status = MiniportHwInitialize(&DeviceExtension->Miniport); if (!NT_SUCCESS(Status)) diff --git a/drivers/storage/port/storport/miniport.c b/drivers/storage/port/storport/miniport.c index c13a3f37a5f..815e6090315 100644 --- a/drivers/storage/port/storport/miniport.c +++ b/drivers/storage/port/storport/miniport.c @@ -346,4 +346,20 @@ MiniportHwInitialize( return Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; } + +BOOLEAN +MiniportHwInterrupt( + _In_ PMINIPORT Miniport) +{ + BOOLEAN Result; + + DPRINT1("MiniportHwInterrupt(%p)\n", + Miniport); + + Result = Miniport->InitData->HwInterrupt(&Miniport->MiniportExtension->HwDeviceExtension); + DPRINT1("HwInterrupt() returned %u\n", Result); + + return Result; +} + /* EOF */ diff --git a/drivers/storage/port/storport/misc.c b/drivers/storage/port/storport/misc.c index 77102018766..f74fd3516fa 100644 --- a/drivers/storage/port/storport/misc.c +++ b/drivers/storage/port/storport/misc.c @@ -287,6 +287,55 @@ TranslateResourceListAddress( } +NTSTATUS +GetResourceListInterrupt( + PFDO_DEVICE_EXTENSION DeviceExtension, + PULONG Vector, + PKIRQL Irql, + KINTERRUPT_MODE *InterruptMode, + PBOOLEAN ShareVector, + PKAFFINITY Affinity) +{ + PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; + INT i, j; + + DPRINT1("GetResourceListInterrupt(%p)\n", + DeviceExtension); + + FullDescriptor = DeviceExtension->TranslatedResources->List; + for (i = 0; i < DeviceExtension->TranslatedResources->Count; i++) + { + for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++) + { + PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors + j; + + switch (PartialDescriptor->Type) + { + case CmResourceTypeInterrupt: + DPRINT1("Interrupt: Level %lu Vector %lu\n", + PartialDescriptor->u.Interrupt.Level, + PartialDescriptor->u.Interrupt.Vector); + + *Vector = PartialDescriptor->u.Interrupt.Vector; + *Irql = (KIRQL)PartialDescriptor->u.Interrupt.Level; + *InterruptMode = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive; + *ShareVector = (PartialDescriptor->ShareDisposition == CmResourceShareShared) ? TRUE : FALSE; + *Affinity = PartialDescriptor->u.Interrupt.Affinity; + + return STATUS_SUCCESS; + } + } + + /* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */ + FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(FullDescriptor->PartialResourceList.PartialDescriptors + + FullDescriptor->PartialResourceList.Count); + } + + return STATUS_NOT_FOUND; +} + + NTSTATUS AllocateAddressMapping( PMAPPED_ADDRESS *MappedAddressList, diff --git a/drivers/storage/port/storport/precomp.h b/drivers/storage/port/storport/precomp.h index 168c3185441..5bd16f338f7 100644 --- a/drivers/storage/port/storport/precomp.h +++ b/drivers/storage/port/storport/precomp.h @@ -101,6 +101,8 @@ typedef struct _FDO_DEVICE_EXTENSION PHYSICAL_ADDRESS UncachedExtensionPhysicalBase; ULONG UncachedExtensionSize; PHW_PASSIVE_INITIALIZE_ROUTINE HwPassiveInitRoutine; + PKINTERRUPT Interrupt; + ULONG InterruptIrql; } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; @@ -140,6 +142,9 @@ NTSTATUS MiniportHwInitialize( _In_ PMINIPORT Miniport); +BOOLEAN +MiniportHwInterrupt( + _In_ PMINIPORT Miniport); /* misc.c */ @@ -182,6 +187,15 @@ TranslateResourceListAddress( BOOLEAN InIoSpace, PPHYSICAL_ADDRESS TranslatedAddress); +NTSTATUS +GetResourceListInterrupt( + PFDO_DEVICE_EXTENSION DeviceExtension, + PULONG Vector, + PKIRQL Irql, + KINTERRUPT_MODE *InterruptMode, + PBOOLEAN ShareVector, + PKAFFINITY Affinity); + NTSTATUS AllocateAddressMapping( PMAPPED_ADDRESS *MappedAddressList,