[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH v2 2/4] Re-work interrupt code in FDO
This patch adds code to the FDO handler to acquire extra message signaled (i.e. edge triggered) interrupt vectors that can be used for per-CPU event channel upcalls (with extra support in Xen). The existing callback via is also limited to upcall on CPU 0 meaning the interrupt callback in the EVTCHN code can pass the current CPU value through to the ABI. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- src/common/names.h | 122 ++++++- src/xenbus.inf | 8 +- src/xenbus/evtchn.c | 55 +++- src/xenbus/fdo.c | 894 +++++++++++++++++++++++++++++++++++++++++----------- src/xenbus/fdo.h | 39 ++- src/xenbus/pdo.c | 2 +- 6 files changed, 896 insertions(+), 224 deletions(-) diff --git a/src/common/names.h b/src/common/names.h index 89894b9..f4a8bd0 100644 --- a/src/common/names.h +++ b/src/common/names.h @@ -196,32 +196,124 @@ PnpMinorFunctionName( } static FORCEINLINE const CHAR * -PartialResourceDescriptorTypeName( +ResourceDescriptorTypeName( IN UCHAR Type ) { -#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type) \ - case CmResourceType ## _Type: \ +#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type) \ + case CmResourceType ## _Type: \ return #_Type; switch (Type) { - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData); - _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate); + _RESOURCE_DESCRIPTOR_TYPE_NAME(Null); + _RESOURCE_DESCRIPTOR_TYPE_NAME(Port); + _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt); + _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory); + _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma); + _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific); + _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber); + _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge); + _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData); + _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate); default: break; } return "UNKNOWN"; -#undef _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME +#undef _RESOURCE_DESCRIPTOR_TYPE_NAME +} + +static FORCEINLINE const CHAR * +ResourceDescriptorShareDispositionName( + IN UCHAR Disposition + ) +{ +#define _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition) \ + case CmResourceShare ## _Disposition: \ + return #_Disposition; + + switch (Disposition) { + _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined); + _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive); + _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive); + _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared); + default: + break; + } + + return "UNKNOWN"; + +#undef _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME +} + +static FORCEINLINE const CHAR * +IrqDevicePolicyName( + IN IRQ_DEVICE_POLICY Policy + ) +{ +#define _IRQ_DEVICE_POLICY_NAME(_Policy) \ + case IrqPolicy ## _Policy: \ + return #_Policy; + + switch (Policy) { + _IRQ_DEVICE_POLICY_NAME(MachineDefault); + _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors); + _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor); + _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine); + _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors); + _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors); + default: + break; + } + + return "UNKNOWN"; + +#undef _IRQ_DEVICE_POLICY_NAME +} + +static FORCEINLINE const CHAR * +IrqPriorityName( + IN IRQ_PRIORITY Priority + ) +{ +#define _IRQ_PRIORITY_NAME(_Priority) \ + case IrqPriority ## _Priority: \ + return #_Priority; + + switch (Priority) { + _IRQ_PRIORITY_NAME(Undefined); + _IRQ_PRIORITY_NAME(Low); + _IRQ_PRIORITY_NAME(Normal); + _IRQ_PRIORITY_NAME(High); + default: + break; + } + + return "UNKNOWN"; + +#undef _IRQ_PRIORITY_NAME +} + +static FORCEINLINE const CHAR * +InterruptModeName( + IN KINTERRUPT_MODE Mode + ) +{ +#define _INTERRUPT_MODE_NAME(_Mode) \ + case _Mode: \ + return #_Mode; + + switch (Mode) { + _INTERRUPT_MODE_NAME(LevelSensitive); + _INTERRUPT_MODE_NAME(Latched); + default: + break; + } + + return "UNKNOWN"; + +#undef _INTERRUPT_MODE_NAME } static FORCEINLINE const CHAR * @@ -358,4 +450,6 @@ BusQueryIdTypeName( #undef _BUS_QUERY_ID_TYPE_NAME } + + #endif // _COMMON_NAMES_H_ diff --git a/src/xenbus.inf b/src/xenbus.inf index 544bb2c..669e866 100644 --- a/src/xenbus.inf +++ b/src/xenbus.inf @@ -82,16 +82,22 @@ StartType=%SERVICE_BOOT_START% ErrorControl=%SERVICE_ERROR_NORMAL% ServiceBinary=%12%\xenbus.sys LoadOrderGroup="Boot Bus Extender" -AddReg = XenBus_Parameters, XenBus_Interfaces +AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts [XenBus_Parameters] HKR,"Parameters",,0x00000010 HKR,"Parameters","SupportedClasses",0x00010000,"VIF","VBD","IFACE" HKR,"Parameters","SyntheticClasses",0x00010000,"IFACE" +HKR,"Parameters","ExtraInterrupts",0x00010001,64 [XenBus_Interfaces] HKR,"Interfaces",,0x00000010 +[XenBus_Interrupts] +HKR,"Interrupt Management",,0x00000010 +HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010 +HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1 + [XenFilt_Service] DisplayName=%XenFiltDesc% ServiceType=%SERVICE_KERNEL_DRIVER% diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c index 1bd5e5f..44043d4 100644 --- a/src/xenbus/evtchn.c +++ b/src/xenbus/evtchn.c @@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT { PXENBUS_FDO Fdo; KSPIN_LOCK Lock; LONG References; - ULONG Vector; + PXENBUS_INTERRUPT Interrupt; BOOLEAN Enabled; XENBUS_SUSPEND_INTERFACE SuspendInterface; PXENBUS_SUSPEND_CALLBACK SuspendCallbackEarly; @@ -127,11 +127,14 @@ EvtchnInterruptEnable( IN PXENBUS_EVTCHN_CONTEXT Context ) { + ULONG Line; NTSTATUS status; Trace("<===>\n"); - status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector); + Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt); + + status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line); ASSERT(NT_SUCCESS(status)); } @@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock( IN PXENBUS_EVTCHN_CONTEXT Context ) { - return FdoAcquireInterruptLock(Context->Fdo); + return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt); } static FORCEINLINE @@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock( IN __drv_restoresIRQL KIRQL Irql ) { - FdoReleaseInterruptLock(Context->Fdo, Irql); + FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql); } static NTSTATUS @@ -644,21 +647,32 @@ done: return DoneSomething; } +static +_Function_class_(KSERVICE_ROUTINE) +__drv_requiresIRQL(HIGH_LEVEL) BOOLEAN -EvtchnInterrupt( - IN PXENBUS_EVTCHN_CONTEXT Context +EvtchnInterruptCallback( + IN PKINTERRUPT InterruptObject, + IN PVOID Argument ) { - BOOLEAN DoneSomething; + PXENBUS_EVTCHN_CONTEXT Context = Argument; + ULONG Cpu; + BOOLEAN DoneSomething; + + UNREFERENCED_PARAMETER(InterruptObject); + + ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); + Cpu = KeGetCurrentProcessorNumber(); DoneSomething = FALSE; while (XENBUS_SHARED_INFO(UpcallPending, &Context->SharedInfoInterface, - 0)) + Cpu)) DoneSomething |= XENBUS_EVTCHN_ABI(Poll, &Context->EvtchnAbi, - 0, + Cpu, EvtchnPollCallback, Context); @@ -857,8 +871,6 @@ EvtchnAcquire( Trace("====>\n"); - Context->Vector = FdoGetInterruptVector(Fdo); - status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface); if (!NT_SUCCESS(status)) goto fail1; @@ -902,6 +914,15 @@ EvtchnAcquire( if (!NT_SUCCESS(status)) goto fail7; + status = FdoAllocateInterrupt(Fdo, + LevelSensitive, + 0, + EvtchnInterruptCallback, + Context, + &Context->Interrupt); + if (!NT_SUCCESS(status)) + goto fail8; + Trace("<====\n"); done: @@ -909,6 +930,11 @@ done: return STATUS_SUCCESS; +fail8: + Error("fail8\n"); + + EvtchnAbiRelease(Context); + fail7: Error("fail7\n"); @@ -948,8 +974,6 @@ fail2: XENBUS_SUSPEND(Release, &Context->SuspendInterface); - Context->Vector = 0; - fail1: Error("fail1 (%08x)\n", status); @@ -978,6 +1002,9 @@ EvtchnRelease( if (!IsListEmpty(&Context->List)) BUG("OUTSTANDING EVENT CHANNELS"); + FdoFreeInterrupt(Context->Fdo, Context->Interrupt); + Context->Interrupt = NULL; + EvtchnAbiRelease(Context); XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface); @@ -1001,8 +1028,6 @@ EvtchnRelease( XENBUS_SUSPEND(Release, &Context->SuspendInterface); - Context->Vector = 0; - Trace("<====\n"); done: diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c index 215c997..cc0c775 100644 --- a/src/xenbus/fdo.c +++ b/src/xenbus/fdo.c @@ -45,6 +45,7 @@ #include "fdo.h" #include "pdo.h" #include "thread.h" +#include "high.h" #include "mutex.h" #include "shared_info.h" #include "evtchn.h" @@ -64,16 +65,17 @@ #define MAXNAMELEN 128 -typedef enum _XENBUS_RESOURCE_TYPE { - MEMORY_RESOURCE = 0, - INTERRUPT_RESOURCE, - RESOURCE_COUNT -} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE; - -typedef struct _XENBUS_RESOURCE { - CM_PARTIAL_RESOURCE_DESCRIPTOR Raw; - CM_PARTIAL_RESOURCE_DESCRIPTOR Translated; -} XENBUS_RESOURCE, *PXENBUS_RESOURCE; +struct _XENBUS_INTERRUPT { + PXENBUS_FDO Fdo; + LIST_ENTRY ListEntry; + KINTERRUPT_MODE InterruptMode; + PKINTERRUPT InterruptObject; + ULONG Cpu; + UCHAR Vector; + ULONG Line; + PKSERVICE_ROUTINE Callback; + PVOID Argument; +}; struct _XENBUS_FDO { PXENBUS_DX Dx; @@ -108,8 +110,8 @@ struct _XENBUS_FDO { PXENBUS_STORE_WATCH BalloonWatch; MUTEX BalloonSuspendMutex; - XENBUS_RESOURCE Resource[RESOURCE_COUNT]; - PKINTERRUPT InterruptObject; + PCM_PARTIAL_RESOURCE_LIST RawResourceList; + PCM_PARTIAL_RESOURCE_LIST TranslatedResourceList; PXENBUS_SUSPEND_CONTEXT SuspendContext; PXENBUS_SHARED_INFO_CONTEXT SharedInfoContext; @@ -129,9 +131,11 @@ struct _XENBUS_FDO { XENBUS_BALLOON_INTERFACE BalloonInterface; XENFILT_UNPLUG_INTERFACE UnplugInterface; + PXENBUS_RANGE_SET RangeSet; + LIST_ENTRY List; + PXENBUS_EVTCHN_CHANNEL Channel; PXENBUS_SUSPEND_CALLBACK SuspendCallbackLate; - PXENBUS_RANGE_SET RangeSet; }; static FORCEINLINE PVOID @@ -187,6 +191,16 @@ __FdoGetDevicePnpState( return Dx->DevicePnpState; } +static FORCEINLINE DEVICE_PNP_STATE +__FdoGetPreviousDevicePnpState( + IN PXENBUS_FDO Fdo + ) +{ + PXENBUS_DX Dx = Fdo->Dx; + + return Dx->PreviousDevicePnpState; +} + static FORCEINLINE VOID __FdoSetDevicePowerState( IN PXENBUS_FDO Fdo, @@ -1383,219 +1397,595 @@ loop: } static VOID -FdoParseResources( +FdoDumpIoResourceDescriptor( IN PXENBUS_FDO Fdo, - IN PCM_RESOURCE_LIST RawResourceList, - IN PCM_RESOURCE_LIST TranslatedResourceList + IN PIO_RESOURCE_DESCRIPTOR Descriptor ) { - PCM_PARTIAL_RESOURCE_LIST RawPartialList; - PCM_PARTIAL_RESOURCE_LIST TranslatedPartialList; - ULONG Index; + Trace("%s: %s\n", + __FdoGetName(Fdo), + ResourceDescriptorTypeName(Descriptor->Type)); + + if (Descriptor->Option == 0) + Trace("Required\n"); + else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE) + Trace("Alternative\n"); + else if (Descriptor->Option == IO_RESOURCE_PREFERRED) + Trace("Preferred\n"); + else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED)) + Trace("Preferred Alternative\n"); + + Trace("ShareDisposition=%s Flags=%04x\n", + ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition), + Descriptor->Flags); + + switch (Descriptor->Type) { + case CmResourceTypeMemory: + Trace("Length = %08x Alignment = %08x\n MinimumAddress = %08x.%08x MaximumAddress = %08x.%08x\n", + Descriptor->u.Memory.Length, + Descriptor->u.Memory.Alignment, + Descriptor->u.Memory.MinimumAddress.HighPart, + Descriptor->u.Memory.MinimumAddress.LowPart, + Descriptor->u.Memory.MaximumAddress.HighPart, + Descriptor->u.Memory.MaximumAddress.LowPart); + break; - ASSERT3U(RawResourceList->Count, ==, 1); - RawPartialList = &RawResourceList->List[0].PartialResourceList; + case CmResourceTypeInterrupt: + Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n", + Descriptor->u.Interrupt.MinimumVector, + Descriptor->u.Interrupt.MaximumVector, + IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy), + IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy), + (PVOID)Descriptor->u.Interrupt.TargetedProcessors); + break; - ASSERT3U(RawPartialList->Version, ==, 1); - ASSERT3U(RawPartialList->Revision, ==, 1); + default: + break; + } +} - ASSERT3U(TranslatedResourceList->Count, ==, 1); - TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList; +static VOID +FdoDumpIoResourceList( + IN PXENBUS_FDO Fdo, + IN PIO_RESOURCE_LIST List + ) +{ + ULONG Index; - ASSERT3U(TranslatedPartialList->Version, ==, 1); - ASSERT3U(TranslatedPartialList->Revision, ==, 1); + for (Index = 0; Index < List->Count; Index++) { + PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index]; - for (Index = 0; Index < TranslatedPartialList->Count; Index++) { - PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor; - PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor; + Trace("%s: %d\n", + __FdoGetName(Fdo), + Index); - RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index]; - TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index]; + FdoDumpIoResourceDescriptor(Fdo, Descriptor); + } +} - Trace("%s: [%d] %02x:%s\n", - __FdoGetName(Fdo), - Index, - TranslatedPartialDescriptor->Type, - PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type)); - - switch (TranslatedPartialDescriptor->Type) { - case CmResourceTypeMemory: - Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n", - RawPartialDescriptor->ShareDisposition, - RawPartialDescriptor->Flags, - RawPartialDescriptor->u.Memory.Start.HighPart, - RawPartialDescriptor->u.Memory.Start.LowPart, - RawPartialDescriptor->u.Memory.Length); - - Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n", - TranslatedPartialDescriptor->ShareDisposition, - TranslatedPartialDescriptor->Flags, - TranslatedPartialDescriptor->u.Memory.Start.HighPart, - TranslatedPartialDescriptor->u.Memory.Start.LowPart, - TranslatedPartialDescriptor->u.Memory.Length); - - Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor; - Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor; +static NTSTATUS +FdoFilterResourceRequirements( + IN PXENBUS_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_RESOURCE_REQUIREMENTS_LIST Old; + ULONG Size; + PIO_RESOURCE_REQUIREMENTS_LIST New; + IO_RESOURCE_DESCRIPTOR Interrupt; + PIO_RESOURCE_LIST List; + ULONG Index; + NTSTATUS status; - break; + status = FdoForwardIrpSynchronously(Fdo, Irp); + if (!NT_SUCCESS(status)) + goto fail1; - case CmResourceTypeInterrupt: - Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n", - RawPartialDescriptor->ShareDisposition, - RawPartialDescriptor->Flags, - RawPartialDescriptor->u.Interrupt.Level, - RawPartialDescriptor->u.Interrupt.Vector, - (PVOID)RawPartialDescriptor->u.Interrupt.Affinity); + if (!__FdoIsActive(Fdo)) + goto not_active; - Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n", - TranslatedPartialDescriptor->ShareDisposition, - TranslatedPartialDescriptor->Flags, - TranslatedPartialDescriptor->u.Interrupt.Level, - TranslatedPartialDescriptor->u.Interrupt.Vector, - (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity); + Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information; + ASSERT3U(Old->AlternativeLists, ==, 1); - Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor; - Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor; + Size = Old->ListSize + + (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors); - break; + New = __AllocatePoolWithTag(PagedPool, Size, 'SUB'); - default: - break; + status = STATUS_NO_MEMORY; + if (New == NULL) + goto fail2; + + RtlCopyMemory(New, Old, Old->ListSize); + New->ListSize = Size; + + List = &New->List[0]; + + for (Index = 0; Index < List->Count; Index++) { + PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index]; + + if (Descriptor->Type != CmResourceTypeInterrupt) + continue; + + Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED; + Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors; + Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1; + } + + RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR)); + Interrupt.Option = 0; // Required + Interrupt.Type = CmResourceTypeInterrupt; + Interrupt.ShareDisposition = CmResourceShareDeviceExclusive; + Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED | + CM_RESOURCE_INTERRUPT_MESSAGE | + CM_RESOURCE_INTERRUPT_POLICY_INCLUDED; + + Interrupt.u.Interrupt.MinimumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN; + Interrupt.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN; + Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors; + Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined; + + for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) { + Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index; + List->Descriptors[List->Count++] = Interrupt; + } + + FdoDumpIoResourceList(Fdo, List); + + Irp->IoStatus.Information = (ULONG_PTR)New; + status = STATUS_SUCCESS; + + ExFreePool(Old); + +not_active: + status = Irp->IoStatus.Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + +static VOID +FdoDumpCmPartialResourceDescriptor( + IN PXENBUS_FDO Fdo, + IN BOOLEAN Translated, + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor + ) +{ + Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n", + __FdoGetName(Fdo), + (Translated) ? "TRANSLATED" : "RAW", + ResourceDescriptorTypeName(Descriptor->Type), + ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition), + Descriptor->Flags); + + switch (Descriptor->Type) { + case CmResourceTypeMemory: + Trace("%s: %s: Start = %08x.%08x Length = %08x\n", + __FdoGetName(Fdo), + (Translated) ? "TRANSLATED" : "RAW", + Descriptor->u.Memory.Start.HighPart, + Descriptor->u.Memory.Start.LowPart, + Descriptor->u.Memory.Length); + break; + + case CmResourceTypeInterrupt: + if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) { + if (Translated) + Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity = %p\n", + __FdoGetName(Fdo), + Descriptor->u.MessageInterrupt.Translated.Level, + Descriptor->u.MessageInterrupt.Translated.Vector, + (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity); + else + Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity = %p\n", + __FdoGetName(Fdo), + Descriptor->u.MessageInterrupt.Raw.MessageCount, + Descriptor->u.MessageInterrupt.Raw.Vector, + (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity); + } else { + Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n", + __FdoGetName(Fdo), + (Translated) ? "TRANSLATED" : "RAW", + Descriptor->u.Interrupt.Level, + Descriptor->u.Interrupt.Vector, + (PVOID)Descriptor->u.Interrupt.Affinity); } + break; + default: + break; } +} - Trace("<====\n"); +static VOID +FdoDumpCmPartialResourceList( + IN PXENBUS_FDO Fdo, + IN BOOLEAN Translated, + IN PCM_PARTIAL_RESOURCE_LIST List + ) +{ + ULONG Index; + + Trace("%s: %s: Version = %d Revision = %d Count = %d\n", + __FdoGetName(Fdo), + (Translated) ? "TRANSLATED" : "RAW", + List->Version, + List->Revision, + List->Count); + + for (Index = 0; Index < List->Count; Index++) { + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index]; + + Trace("%s: %s: %d\n", + __FdoGetName(Fdo), + (Translated) ? "TRANSLATED" : "RAW", + Index); + + FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor); + } } -static FORCEINLINE PXENBUS_RESOURCE -__FdoGetResource( - IN PXENBUS_FDO Fdo, - IN XENBUS_RESOURCE_TYPE Type +static VOID +FdoDumpCmFullResourceDescriptor( + IN PXENBUS_FDO Fdo, + IN BOOLEAN Translated, + IN PCM_FULL_RESOURCE_DESCRIPTOR Descriptor ) { - ASSERT3U(Type, <, RESOURCE_COUNT); + Trace("%s: %s: InterfaceType = %s BusNumber = %d\n", + __FdoGetName(Fdo), + (Translated) ? "TRANSLATED" : "RAW", + InterfaceTypeName(Descriptor->InterfaceType), + Descriptor->BusNumber); - return &Fdo->Resource[Type]; + FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor->PartialResourceList); +} + +static VOID +FdoDumpCmResourceList( + IN PXENBUS_FDO Fdo, + IN BOOLEAN Translated, + IN PCM_RESOURCE_LIST List + ) +{ + FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]); +} + +_IRQL_requires_max_(HIGH_LEVEL) +_IRQL_saves_ +_IRQL_raises_(HIGH_LEVEL) +KIRQL +FdoAcquireInterruptLock( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt + ) +{ + UNREFERENCED_PARAMETER(Fdo); + + return KeAcquireInterruptSpinLock(Interrupt->InterruptObject); +} + +_IRQL_requires_(HIGH_LEVEL) +VOID +FdoReleaseInterruptLock( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt, + IN __drv_restoresIRQL KIRQL Irql + ) +{ + UNREFERENCED_PARAMETER(Fdo); + + KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql); } static _Function_class_(KSERVICE_ROUTINE) -_IRQL_requires_(HIGH_LEVEL) -_IRQL_requires_same_ +__drv_requiresIRQL(HIGH_LEVEL) BOOLEAN -FdoInterrupt( +FdoInterruptCallback( IN PKINTERRUPT InterruptObject, IN PVOID Context ) { - PXENBUS_FDO Fdo = Context; + PXENBUS_INTERRUPT Interrupt = Context; - UNREFERENCED_PARAMETER(InterruptObject); + if (Interrupt->Callback == NULL) + return FALSE; - ASSERT(Fdo != NULL); - - return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo)); + return Interrupt->Callback(InterruptObject, + Interrupt->Argument); } static NTSTATUS FdoConnectInterrupt( - IN PXENBUS_FDO Fdo + IN PXENBUS_FDO Fdo, + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw, + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, + OUT PXENBUS_INTERRUPT *Interrupt ) { - PXENBUS_RESOURCE Interrupt; - IO_CONNECT_INTERRUPT_PARAMETERS Connect; - NTSTATUS status; + IO_CONNECT_INTERRUPT_PARAMETERS Connect; + ULONG Cpu; + NTSTATUS status; Trace("====>\n"); - Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE); + *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT)); + + status = STATUS_NO_MEMORY; + if (*Interrupt == NULL) + goto fail1; + + (*Interrupt)->Fdo = Fdo; + (*Interrupt)->InterruptMode = (Translated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? + Latched : + LevelSensitive; + + if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) + (*Interrupt)->Line = Raw->u.Interrupt.Vector; RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS)); Connect.Version = CONNECT_FULLY_SPECIFIED; Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo); - Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt->Translated.u.Interrupt.Level; - Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt->Translated.ShareDisposition == CmResourceShareShared); - Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector; - Connect.FullySpecified.Irql = (KIRQL)Interrupt->Translated.u.Interrupt.Level; - Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? - Latched : - LevelSensitive; - Connect.FullySpecified.ProcessorEnableMask = Interrupt->Translated.u.Interrupt.Affinity; - Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject; - Connect.FullySpecified.ServiceRoutine = FdoInterrupt; - Connect.FullySpecified.ServiceContext = Fdo; + Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared); + Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode; + Connect.FullySpecified.InterruptObject = &(*Interrupt)->InterruptObject; + Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback; + Connect.FullySpecified.ServiceContext = *Interrupt; + + if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) { + Connect.FullySpecified.Vector = Translated->u.MessageInterrupt.Translated.Vector; + Connect.FullySpecified.Irql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level; + Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level; + Connect.FullySpecified.ProcessorEnableMask = Translated->u.MessageInterrupt.Translated.Affinity; + } else { + Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector; + Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level; + Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.Interrupt.Level; + Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity; + } status = IoConnectInterruptEx(&Connect); if (!NT_SUCCESS(status)) - goto fail1; + goto fail2; + + (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector; + +#if defined(__i386__) + (VOID)_BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask); +#elif defined(__x86_64__) + (VOID)_BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask); +#else +#error 'Unrecognised architecture' +#endif + + (*Interrupt)->Cpu = Cpu; + + Info("%p: %s %s CPU %u VECTOR %02x\n", + (*Interrupt)->InterruptObject, + ResourceDescriptorShareDispositionName(Translated->ShareDisposition), + InterruptModeName((*Interrupt)->InterruptMode), + (*Interrupt)->Cpu, + (*Interrupt)->Vector); Trace("<====\n"); return STATUS_SUCCESS; +fail2: + Error("fail2\n"); + + __FdoFree(*Interrupt); + *Interrupt = NULL; + fail1: Error("fail1 (%08x)\n", status); return status; } -_IRQL_requires_max_(HIGH_LEVEL) -_IRQL_saves_ -_IRQL_raises_(HIGH_LEVEL) -KIRQL -FdoAcquireInterruptLock( - IN PXENBUS_FDO Fdo +static VOID +FdoDisconnectInterrupt( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt ) { - PKINTERRUPT InterruptObject = Fdo->InterruptObject; + IO_DISCONNECT_INTERRUPT_PARAMETERS Disconnect; + + UNREFERENCED_PARAMETER(Fdo); + + Trace("====>\n"); + + Info("%p: CPU %u VECTOR %02x\n", + Interrupt->InterruptObject, + Interrupt->Cpu, + Interrupt->Vector); + + Interrupt->Cpu = 0; + Interrupt->Vector = 0; + + RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS)); + Disconnect.Version = CONNECT_FULLY_SPECIFIED; + Disconnect.ConnectionContext.InterruptObject = Interrupt->InterruptObject; - return KeAcquireInterruptSpinLock(InterruptObject); + IoDisconnectInterruptEx(&Disconnect); + + Interrupt->Line = 0; + Interrupt->InterruptObject = NULL; + Interrupt->InterruptMode = 0; + Interrupt->Fdo = NULL; + + ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT))); + __FdoFree(Interrupt); + + Trace("<====\n"); } - -_IRQL_requires_(HIGH_LEVEL) -VOID -FdoReleaseInterruptLock( - IN PXENBUS_FDO Fdo, - IN __drv_restoresIRQL KIRQL Irql + +static NTSTATUS +FdoCreateInterrupt( + IN PXENBUS_FDO Fdo ) { - PKINTERRUPT InterruptObject = Fdo->InterruptObject; + ULONG Index; + PXENBUS_INTERRUPT Interrupt; + NTSTATUS status; + + InitializeListHead(&Fdo->List); + + for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) { + PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo->RawResourceList->PartialDescriptors[Index]; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index]; + + if (Translated->Type != CmResourceTypeInterrupt) + continue; + + status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt); + if (!NT_SUCCESS(status)) + goto fail1; + + InsertTailList(&Fdo->List, &Interrupt->ListEntry); + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + while (!IsListEmpty(&Fdo->List)) { + PLIST_ENTRY ListEntry; + + ListEntry = RemoveHeadList(&Fdo->List); + ASSERT(ListEntry != &Fdo->List); + + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); + + Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry); + + FdoDisconnectInterrupt(Fdo, Interrupt); + } + + RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY)); - KeReleaseInterruptSpinLock(InterruptObject, Irql); + return status; } -ULONG +NTSTATUS +FdoAllocateInterrupt( + IN PXENBUS_FDO Fdo, + IN KINTERRUPT_MODE InterruptMode, + IN ULONG Cpu, + IN KSERVICE_ROUTINE Callback, + IN PVOID Argument OPTIONAL, + OUT PXENBUS_INTERRUPT *Interrupt + ) +{ + PLIST_ENTRY ListEntry; + KIRQL Irql; + NTSTATUS status; + + for (ListEntry = Fdo->List.Flink; + ListEntry != &Fdo->List; + ListEntry = ListEntry->Flink) { + *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry); + + if ((*Interrupt)->Callback == NULL && + (*Interrupt)->InterruptMode == InterruptMode && + (*Interrupt)->Cpu == Cpu) + goto found; + } + + *Interrupt = NULL; + + status = STATUS_OBJECT_NAME_NOT_FOUND; + goto fail1; + +found: + Irql = FdoAcquireInterruptLock(Fdo, *Interrupt); + (*Interrupt)->Callback = Callback; + (*Interrupt)->Argument = Argument; + FdoReleaseInterruptLock(Fdo, *Interrupt, Irql); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +UCHAR FdoGetInterruptVector( - IN PXENBUS_FDO Fdo + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt + ) +{ + UNREFERENCED_PARAMETER(Fdo); + + return Interrupt->Vector; +} + +ULONG +FdoGetInterruptLine( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt ) { - PXENBUS_RESOURCE Interrupt; + UNREFERENCED_PARAMETER(Fdo); + + return Interrupt->Line; +} - Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE); +VOID +FdoFreeInterrupt( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt + ) +{ + KIRQL Irql; - return Interrupt->Raw.u.Interrupt.Vector; + Irql = FdoAcquireInterruptLock(Fdo, Interrupt); + Interrupt->Callback = NULL; + Interrupt->Argument = NULL; + FdoReleaseInterruptLock(Fdo, Interrupt, Irql); } static VOID -FdoDisconnectInterrupt( - IN PXENBUS_FDO Fdo +FdoDestroyInterrupt( + IN PXENBUS_FDO Fdo ) { - PKINTERRUPT InterruptObject; - IO_DISCONNECT_INTERRUPT_PARAMETERS Disconnect; + while (!IsListEmpty(&Fdo->List)) { + PLIST_ENTRY ListEntry; + PXENBUS_INTERRUPT Interrupt; - Trace("====>\n"); + ListEntry = RemoveHeadList(&Fdo->List); + ASSERT(ListEntry != &Fdo->List); - InterruptObject = Fdo->InterruptObject; - Fdo->InterruptObject = NULL; + RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY)); - RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS)); - Disconnect.Version = CONNECT_FULLY_SPECIFIED; - Disconnect.ConnectionContext.InterruptObject = InterruptObject; + Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry); - IoDisconnectInterruptEx(&Disconnect); +#pragma warning(push) +#pragma warning(disable:4054) // 'type cast' : from function pointer to data pointer + ASSERT3P(Interrupt->Callback, ==, NULL); +#pragma warning(pop) - Trace("<====\n"); + ASSERT3P(Interrupt->Argument, ==, NULL); + + FdoDisconnectInterrupt(Fdo, Interrupt); + } + + RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY)); } static @@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate( static NTSTATUS FdoCreateIoSpace( - IN PXENBUS_FDO Fdo + IN PXENBUS_FDO Fdo ) { - PXENBUS_RESOURCE Memory; - NTSTATUS status; + ULONG Index; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated; + PHYSICAL_ADDRESS End; + NTSTATUS status; + + for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) { + Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index]; - Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE); + if (Translated->Type == CmResourceTypeMemory) + goto found; + } + + status = STATUS_OBJECT_NAME_NOT_FOUND; + goto fail1; +found: status = XENBUS_RANGE_SET(Create, &Fdo->RangeSetInterface, "io_space", &Fdo->RangeSet); if (!NT_SUCCESS(status)) - goto fail1; + goto fail2; status = XENBUS_RANGE_SET(Put, &Fdo->RangeSetInterface, Fdo->RangeSet, - Memory->Translated.u.Memory.Start.QuadPart, - Memory->Translated.u.Memory.Length); + Translated->u.Memory.Start.QuadPart, + Translated->u.Memory.Length); if (!NT_SUCCESS(status)) - goto fail2; + goto fail3; + + End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated->u.Memory.Length - 1; + + Info("%08x.%08x - %08x.%08x\n", + Translated->u.Memory.Start.HighPart, + Translated->u.Memory.Start.LowPart, + End.HighPart, + End.LowPart); return STATUS_SUCCESS; -fail2: - Error("fail2\n"); +fail3: + Error("fail3\n"); XENBUS_RANGE_SET(Destroy, &Fdo->RangeSetInterface, Fdo->RangeSet); Fdo->RangeSet = NULL; +fail2: + Error("fail2\n"); + fail1: Error("fail1 (%08x)\n", status); @@ -1890,19 +2302,29 @@ FdoFreeIoSpace( static VOID FdoDestroyIoSpace( - IN PXENBUS_FDO Fdo + IN PXENBUS_FDO Fdo ) { - PXENBUS_RESOURCE Memory; - NTSTATUS status; + ULONG Index; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated; + NTSTATUS status; + + for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) { + Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index]; - Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE); + if (Translated->Type == CmResourceTypeMemory) + goto found; + } + + ASSERT(FALSE); + return; +found: status = XENBUS_RANGE_SET(Get, &Fdo->RangeSetInterface, Fdo->RangeSet, - Memory->Translated.u.Memory.Start.QuadPart, - Memory->Translated.u.Memory.Length); + Translated->u.Memory.Start.QuadPart, + Translated->u.Memory.Length); ASSERT(NT_SUCCESS(status)); XENBUS_RANGE_SET(Destroy, @@ -2214,39 +2636,111 @@ FdoS3ToS4( Trace("<====\n"); } +static VOID +FdoFilterCmPartialResourceList( + IN PXENBUS_FDO Fdo, + IN PCM_PARTIAL_RESOURCE_LIST List + ) +{ + ULONG Index; + + UNREFERENCED_PARAMETER(Fdo); + + for (Index = 0; Index < List->Count; Index++) { + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index]; + + // + // These are additional resources that XENBUS requested, so they must + // be filtered out before the underlying PCI bus driver sees them. Happily + // it appears that swapping the type to DevicePrivate causes PCI.SYS to ignore + // them. + // + if (Descriptor->Type == CmResourceTypeInterrupt && + (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)) + Descriptor->Type = CmResourceTypeDevicePrivate; + } +} + static NTSTATUS FdoStartDevice( - IN PXENBUS_FDO Fdo, - IN PIRP Irp + IN PXENBUS_FDO Fdo, + IN PIRP Irp ) { - PIO_STACK_LOCATION StackLocation; - NTSTATUS status; + PIO_STACK_LOCATION StackLocation; + PCM_RESOURCE_LIST ResourceList; + PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; + ULONG Size; + NTSTATUS status; ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - status = FdoForwardIrpSynchronously(Fdo, Irp); - if (!NT_SUCCESS(status)) + StackLocation = IoGetCurrentIrpStackLocation(Irp); + + // Raw + + ResourceList = StackLocation->Parameters.StartDevice.AllocatedResources; + FdoDumpCmResourceList(Fdo, FALSE, ResourceList); + + ASSERT3U(ResourceList->Count, ==, 1); + Descriptor = &ResourceList->List[0]; + + ASSERT3U(Descriptor->InterfaceType, ==, PCIBus); + ASSERT3U(Descriptor->BusNumber, ==, 0); + + Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) + + (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR); + + Fdo->RawResourceList = __FdoAllocate(Size); + + status = STATUS_NO_MEMORY; + if (Fdo->RawResourceList == NULL) goto fail1; - StackLocation = IoGetCurrentIrpStackLocation(Irp); + RtlCopyMemory(Fdo->RawResourceList, &Descriptor->PartialResourceList, Size); + + FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList); + + // Translated + + ResourceList = StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated; + FdoDumpCmResourceList(Fdo, TRUE, ResourceList); + + ASSERT3U(ResourceList->Count, ==, 1); + Descriptor = &ResourceList->List[0]; + + ASSERT3U(Descriptor->InterfaceType, ==, PCIBus); + ASSERT3U(Descriptor->BusNumber, ==, 0); + + Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) + + (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR); + + Fdo->TranslatedResourceList = __FdoAllocate(Size); + + status = STATUS_NO_MEMORY; + if (Fdo->TranslatedResourceList == NULL) + goto fail2; + + RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor->PartialResourceList, Size); + + FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList); - FdoParseResources(Fdo, - StackLocation->Parameters.StartDevice.AllocatedResources, - StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated); + status = FdoForwardIrpSynchronously(Fdo, Irp); + if (!NT_SUCCESS(status)) + goto fail3; if (!__FdoIsActive(Fdo)) goto not_active; - status = FdoConnectInterrupt(Fdo); + status = FdoCreateInterrupt(Fdo); if (!NT_SUCCESS(status)) - goto fail2; + goto fail4; KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE); status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread); if (!NT_SUCCESS(status)) - goto fail3; + goto fail5; InitializeMutex(&Fdo->BalloonSuspendMutex); @@ -2254,20 +2748,20 @@ FdoStartDevice( status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread); if (!NT_SUCCESS(status)) - goto fail4; + goto fail6; if (Fdo->BalloonInterface.Interface.Context != NULL) { KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE); status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread); if (!NT_SUCCESS(status)) - goto fail5; + goto fail7; } not_active: status = FdoD3ToD0(Fdo); if (!NT_SUCCESS(status)) - goto fail6; + goto fail8; if (Fdo->BalloonInterface.Interface.Context != NULL) { BOOLEAN Warned; @@ -2306,11 +2800,11 @@ not_active: return status; -fail6: - Error("fail6\n"); +fail8: + Error("fail8\n"); if (!__FdoIsActive(Fdo)) - goto fail2; + goto fail4; if (Fdo->BalloonInterface.Interface.Context != NULL) { ThreadAlert(Fdo->BalloonThread); @@ -2318,8 +2812,8 @@ fail6: Fdo->BalloonThread = NULL; } -fail5: - Error("fail5\n"); +fail7: + Error("fail7\n"); if (Fdo->BalloonInterface.Interface.Context != NULL) RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT)); @@ -2328,8 +2822,8 @@ fail5: ThreadJoin(Fdo->SuspendThread); Fdo->SuspendThread = NULL; -fail4: - Error("fail4\n"); +fail6: + Error("fail6\n"); RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT)); @@ -2339,17 +2833,27 @@ fail4: ThreadJoin(Fdo->ScanThread); Fdo->ScanThread = NULL; -fail3: - Error("fail3\n"); +fail5: + Error("fail5\n"); RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT)); - FdoDisconnectInterrupt(Fdo); + FdoDestroyInterrupt(Fdo); + +fail4: + Error("fail4\n"); + +fail3: + Error("fail3\n"); + + __FdoFree(Fdo->TranslatedResourceList); + Fdo->TranslatedResourceList = NULL; fail2: Error("fail2\n"); - RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT); + __FdoFree(Fdo->RawResourceList); + Fdo->RawResourceList = NULL; fail1: Error("fail1 (%08x)\n", status); @@ -2445,10 +2949,14 @@ FdoStopDevice( RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT)); - FdoDisconnectInterrupt(Fdo); + FdoDestroyInterrupt(Fdo); not_active: - RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT); + __FdoFree(Fdo->TranslatedResourceList); + Fdo->TranslatedResourceList = NULL; + + __FdoFree(Fdo->RawResourceList); + Fdo->RawResourceList = NULL; __FdoSetDevicePnpState(Fdo, Stopped); Irp->IoStatus.Status = STATUS_SUCCESS; @@ -2554,6 +3062,9 @@ FdoRemoveDevice( ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + if (__FdoGetPreviousDevicePnpState(Fdo) != Started) + goto done; + if (__FdoIsActive(Fdo)) { Trace("waiting for scan thread...\n"); @@ -2621,11 +3132,16 @@ FdoRemoveDevice( RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT)); - FdoDisconnectInterrupt(Fdo); + FdoDestroyInterrupt(Fdo); not_active: - RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT); + __FdoFree(Fdo->TranslatedResourceList); + Fdo->TranslatedResourceList = NULL; + + __FdoFree(Fdo->RawResourceList); + Fdo->RawResourceList = NULL; +done: __FdoSetDevicePnpState(Fdo, Deleted); Irp->IoStatus.Status = STATUS_SUCCESS; @@ -2937,6 +3453,10 @@ FdoDispatchPnp( PnpMinorFunctionName(MinorFunction)); switch (StackLocation->MinorFunction) { + case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: + status = FdoFilterResourceRequirements(Fdo, Irp); + break; + case IRP_MN_START_DEVICE: status = FdoStartDevice(Fdo, Irp); break; diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h index fdb6f79..4916be4 100644 --- a/src/xenbus/fdo.h +++ b/src/xenbus/fdo.h @@ -38,6 +38,8 @@ #include "driver.h" #include "types.h" +typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, *PXENBUS_INTERRUPT; + extern NTSTATUS FdoCreate( IN PDEVICE_OBJECT PhysicalDeviceObject, @@ -140,11 +142,6 @@ FdoFreeIoSpace( IN ULONG Size ); -extern ULONG -FdoGetInterruptVector( - IN PXENBUS_FDO Fdo - ); - // Disable erroneous SAL warnings around use of interrupt locks #pragma warning(disable:28230) #pragma warning(disable:28285) @@ -155,7 +152,8 @@ _IRQL_saves_ _IRQL_raises_(HIGH_LEVEL) KIRQL FdoAcquireInterruptLock( - IN PXENBUS_FDO Fdo + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt ); extern @@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL) VOID FdoReleaseInterruptLock( IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt, IN __drv_restoresIRQL KIRQL Irql ); +extern NTSTATUS +FdoAllocateInterrupt( + IN PXENBUS_FDO Fdo, + IN KINTERRUPT_MODE InterruptMode, + IN ULONG Cpu, + IN KSERVICE_ROUTINE Callback, + IN PVOID Argument OPTIONAL, + OUT PXENBUS_INTERRUPT *Interrupt + ); + +extern UCHAR +FdoGetInterruptVector( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt + ); + +extern ULONG +FdoGetInterruptLine( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt + ); + +extern VOID +FdoFreeInterrupt( + IN PXENBUS_FDO Fdo, + IN PXENBUS_INTERRUPT Interrupt + ); + #include "suspend.h" extern PXENBUS_SUSPEND_CONTEXT diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c index 650e84d..ad0d4de 100644 --- a/src/xenbus/pdo.c +++ b/src/xenbus/pdo.c @@ -682,7 +682,7 @@ PdoParseResources( __PdoGetName(Pdo), Index, TranslatedPartialDescriptor->Type, - PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type)); + ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type)); switch (TranslatedPartialDescriptor->Type) { case CmResourceTypeMemory: -- 2.1.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |