[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [win-pv-devel] [PATCH 2/4] Re-work interrupt code in FDO
> -----Original Message----- > From: Paul Durrant [mailto:paul.durrant@xxxxxxxxxx] > Sent: 07 November 2014 13:33 > To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx > Cc: Paul Durrant > Subject: [PATCH 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 | 10 +- > src/xenbus/evtchn.c | 55 +++- > src/xenbus/fdo.c | 894 > +++++++++++++++++++++++++++++++++++++++++----------- > src/xenbus/fdo.h | 39 ++- > src/xenbus/pdo.c | 2 +- > 6 files changed, 897 insertions(+), 225 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..b2c17c3 100644 > --- a/src/xenbus.inf > +++ b/src/xenbus.inf > @@ -78,20 +78,26 @@ AddService=xenfilt,,XenFilt_Service, > [XenBus_Service] > DisplayName=%XenBusDesc% > ServiceType=%SERVICE_KERNEL_DRIVER% > -StartType=%SERVICE_BOOT_START% > +StartType=%SERVICE_DEMAND_START% This change was meant to be only for the sake of my own debugging. I'll remove it and re-post. Paul > 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",0x000 > 10001,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 |