|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH v3 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 |