--- /dev/null
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _REVISION_H
+#define _REVISION_H
+
+// Key:
+// S - XENBUS_SUSPEND_INTERFACE
+// SI - XENBUS_SHARED_INFO_INTERFACE
+// E - XENBUS_EVTCHN_INTERFACE
+// D - XENBUS_DEBUG_INTEFACE
+// ST - XENBUS_STORE_INTERFACE
+// R - XENBUS_RANGE_SET_INTERFACE
+// C - XENBUS_CACHE_INTERFACE
+// G - XENBUS_GNTTAB_INTERFACE
+// EM - XENFILT_EMULATED_INTERFACE
+
+// REVISION S SI E D ST R C G EM
+#define DEFINE_REVISION_TABLE \
+ DEFINE_REVISION(0x08000008, 1, 2, 4, 1, 1, 1, 1, 1, 1)
+
+#endif // _REVISION_H
#include <ntstrsafe.h>
#include <emulated_interface.h>
-#include <unplug_interface.h>
#include "names.h"
#include "fdo.h"
#include "assert.h"
#include "util.h"
#include "version.h"
+#include "revision.h"
#define PDO_TAG 'ODP'
BOOLEAN Removable;
BOOLEAN Ejectable;
- PULONG Revision;
- ULONG Count;
-
BUS_INTERFACE_STANDARD BusInterface;
XENBUS_SUSPEND_INTERFACE SuspendInterface;
return __PdoGetFdo(Pdo);
}
-static NTSTATUS
-PdoAddRevision(
- IN PXENBUS_PDO Pdo,
- IN ULONG Revision
- )
-{
- PVOID Buffer;
- ULONG Count;
- NTSTATUS status;
-
- Count = Pdo->Count + 1;
-
- Buffer = __PdoAllocate(sizeof (ULONG) * Count);
-
- status = STATUS_NO_MEMORY;
- if (Buffer == NULL)
- goto fail1;
-
- if (Pdo->Revision != NULL) {
- RtlCopyMemory(Buffer,
- Pdo->Revision,
- sizeof (ULONG) * Pdo->Count);
- __PdoFree(Pdo->Revision);
- }
-
- Pdo->Revision = Buffer;
- Pdo->Revision[Pdo->Count] = Revision;
-
- Pdo->Count++;
- ASSERT3U(Pdo->Count, <=, 64);
-
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
+typedef struct _XENBUS_PDO_REVISION {
+ ULONG Number;
+ ULONG SuspendInterfaceVersion;
+ ULONG SharedInfoInterfaceVersion;
+ ULONG EvtchnInterfaceVersion;
+ ULONG DebugInterfaceVersion;
+ ULONG StoreInterfaceVersion;
+ ULONG RangeSetInterfaceVersion;
+ ULONG CacheInterfaceVersion;
+ ULONG GnttabInterfaceVersion;
+ ULONG EmulatedInterfaceVersion;
+} XENBUS_PDO_REVISION, *PXENBUS_PDO_REVISION;
+
+#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _EM) \
+ { (_N), (_S), (_SI), (_E), (_D), (_ST), (_R), (_C), (_G), (_EM) }
+
+static XENBUS_PDO_REVISION PdoRevision[] = {
+ DEFINE_REVISION_TABLE
+};
- return status;
-}
+#undef DEFINE_REVISION
-static NTSTATUS
-PdoSetRevisions(
+static VOID
+PdoDumpRevisions(
IN PXENBUS_PDO Pdo
)
{
- ULONG Suspend;
- ULONG Revision;
- NTSTATUS status;
-
- Revision = MAJOR_VERSION << 24;
+ ULONG Index;
- // Enumerate all possible combinations of exported interface versions since v1
- // and add a PDO revsion for each combination that's currently supported. Note that
- // the exported interfaces include any interface queries we pass through.
- // We must enumerate from v1 to ensure that revision numbers don't change
- // even when a particular combination of interface versions becomes
- // unsupported. (See README.md for API versioning policy).
-
- for (Suspend = 1; Suspend <= XENBUS_SUSPEND_INTERFACE_VERSION_MAX; Suspend++) {
- ULONG SharedInfo;
-
- for (SharedInfo = 1; SharedInfo <= XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX; SharedInfo++) {
- ULONG Evtchn;
-
- for (Evtchn = 1; Evtchn <= XENBUS_EVTCHN_INTERFACE_VERSION_MAX; Evtchn++) {
- ULONG Debug;
-
- for (Debug = 1; Debug <= XENBUS_DEBUG_INTERFACE_VERSION_MAX; Debug++) {
- ULONG Store;
-
- for (Store = 1; Store <= XENBUS_STORE_INTERFACE_VERSION_MAX; Store++) {
- ULONG RangeSet;
-
- for (RangeSet = 1; RangeSet <= XENBUS_RANGE_SET_INTERFACE_VERSION_MAX; RangeSet++) {
- ULONG Cache;
-
- for (Cache = 1; Cache <= XENBUS_CACHE_INTERFACE_VERSION_MAX; Cache++) {
- ULONG Gnttab;
-
- for (Gnttab = 1; Gnttab <= XENBUS_GNTTAB_INTERFACE_VERSION_MAX; Gnttab++) {
- ULONG Emulated;
-
- for (Emulated = 1; Emulated <= XENFILT_EMULATED_INTERFACE_VERSION_MAX; Emulated++) {
- ULONG Unplug;
-
- for (Unplug = 1; Unplug <= XENFILT_UNPLUG_INTERFACE_VERSION_MAX; Unplug++) {
- Revision++;
-
- if (Suspend >= XENBUS_SUSPEND_INTERFACE_VERSION_MIN &&
- SharedInfo >= XENBUS_SHARED_INFO_INTERFACE_VERSION_MIN &&
- Evtchn >= XENBUS_EVTCHN_INTERFACE_VERSION_MIN &&
- Debug >= XENBUS_DEBUG_INTERFACE_VERSION_MIN &&
- Store >= XENBUS_STORE_INTERFACE_VERSION_MIN &&
- RangeSet >= XENBUS_RANGE_SET_INTERFACE_VERSION_MIN &&
- Cache >= XENBUS_CACHE_INTERFACE_VERSION_MIN &&
- Gnttab >= XENBUS_GNTTAB_INTERFACE_VERSION_MIN &&
- Emulated >= XENFILT_EMULATED_INTERFACE_VERSION_MIN &&
- Unplug >= XENFILT_UNPLUG_INTERFACE_VERSION_MIN) {
- Info("%08X -> "
- "SUSPEND v%u "
- "SHARED_INFO v%u "
- "EVTCHN v%u "
- "DEBUG v%u "
- "STORE v%u "
- "RANGE_SET v%u "
- "CACHE v%u "
- "GNTTAB v%u "
- "EMULATED v%u "
- "UNPLUG v%u\n",
- Revision,
- Suspend,
- SharedInfo,
- Evtchn,
- Debug,
- Store,
- RangeSet,
- Cache,
- Gnttab,
- Emulated,
- Unplug);
-
- status = PdoAddRevision(Pdo, Revision);
- if (!NT_SUCCESS(status))
- goto fail1;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- ASSERT(Pdo->Count > 0);
- return STATUS_SUCCESS;
-
-fail1:
- Error("fail1 (%08x)\n", status);
+ UNREFERENCED_PARAMETER(Pdo);
- if (Pdo->Revision != NULL) {
- __PdoFree(Pdo->Revision);
- Pdo->Revision = NULL;
+ for (Index = 0; Index < ARRAYSIZE(PdoRevision); Index++) {
+ PXENBUS_PDO_REVISION Revision = &PdoRevision[Index];
+
+ ASSERT3U(Revision->SuspendInterfaceVersion, >=, XENBUS_SUSPEND_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->SuspendInterfaceVersion, <=, XENBUS_SUSPEND_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->SuspendInterfaceVersion == XENBUS_SUSPEND_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->SharedInfoInterfaceVersion, >=, XENBUS_SHARED_INFO_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->SharedInfoInterfaceVersion, <=, XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->SharedInfoInterfaceVersion == XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->EvtchnInterfaceVersion, >=, XENBUS_EVTCHN_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->EvtchnInterfaceVersion, <=, XENBUS_EVTCHN_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->EvtchnInterfaceVersion == XENBUS_EVTCHN_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->DebugInterfaceVersion, >=, XENBUS_DEBUG_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->DebugInterfaceVersion, <=, XENBUS_DEBUG_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->DebugInterfaceVersion == XENBUS_DEBUG_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->StoreInterfaceVersion, >=, XENBUS_STORE_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->StoreInterfaceVersion, <=, XENBUS_STORE_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->StoreInterfaceVersion == XENBUS_STORE_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->RangeSetInterfaceVersion, >=, XENBUS_RANGE_SET_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->RangeSetInterfaceVersion, <=, XENBUS_RANGE_SET_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->RangeSetInterfaceVersion == XENBUS_RANGE_SET_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->CacheInterfaceVersion, >=, XENBUS_CACHE_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->CacheInterfaceVersion, <=, XENBUS_CACHE_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->CacheInterfaceVersion == XENBUS_CACHE_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->GnttabInterfaceVersion, >=, XENBUS_GNTTAB_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->GnttabInterfaceVersion, <=, XENBUS_GNTTAB_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->GnttabInterfaceVersion == XENBUS_GNTTAB_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->EmulatedInterfaceVersion, >=, XENFILT_EMULATED_INTERFACE_VERSION_MIN);
+ ASSERT3U(Revision->EmulatedInterfaceVersion, <=, XENFILT_EMULATED_INTERFACE_VERSION_MAX);
+ ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1,
+ Revision->EmulatedInterfaceVersion == XENFILT_EMULATED_INTERFACE_VERSION_MAX));
+
+ ASSERT3U(Revision->Number >> 24, ==, MAJOR_VERSION);
+
+ Info("%08X -> "
+ "SUSPEND v%u "
+ "SHARED_INFO v%u "
+ "EVTCHN v%u "
+ "DEBUG v%u "
+ "STORE v%u "
+ "RANGE_SET v%u "
+ "CACHE v%u "
+ "GNTTAB v%u "
+ "EMULATED v%u\n",
+ Revision->Number,
+ Revision->SuspendInterfaceVersion,
+ Revision->SharedInfoInterfaceVersion,
+ Revision->EvtchnInterfaceVersion,
+ Revision->DebugInterfaceVersion,
+ Revision->StoreInterfaceVersion,
+ Revision->RangeSetInterfaceVersion,
+ Revision->CacheInterfaceVersion,
+ Revision->GnttabInterfaceVersion,
+ Revision->EmulatedInterfaceVersion);
}
-
- Pdo->Count = 0;
-
- return status;
}
static FORCEINLINE PDEVICE_OBJECT
{ &GUID_XENBUS_CACHE_INTERFACE, "CACHE_INTERFACE", PdoQueryCacheInterface },
{ &GUID_XENBUS_GNTTAB_INTERFACE, "GNTTAB_INTERFACE", PdoQueryGnttabInterface },
{ &GUID_XENFILT_EMULATED_INTERFACE, "EMULATED_INTERFACE", PdoDelegateIrp },
- { &GUID_XENFILT_UNPLUG_INTERFACE, "UNPLUG_INTERFACE", PdoDelegateIrp },
{ NULL, NULL, NULL }
};
case BusQueryHardwareIDs:
Trace("BusQueryHardwareIDs\n");
- Id.MaximumLength = (USHORT)(MAX_DEVICE_ID_LEN * Pdo->Count) * sizeof (WCHAR);
+ Id.MaximumLength = (USHORT)(MAX_DEVICE_ID_LEN * ARRAYSIZE(PdoRevision)) * sizeof (WCHAR);
break;
case BusQueryCompatibleIDs:
Trace("BusQueryCompatibleIDs\n");
- Id.MaximumLength = (USHORT)(MAX_DEVICE_ID_LEN * Pdo->Count) * sizeof (WCHAR);
+ Id.MaximumLength = (USHORT)(MAX_DEVICE_ID_LEN * ARRAYSIZE(PdoRevision)) * sizeof (WCHAR);
break;
default:
break;
case BusQueryDeviceID: {
- ULONG Index;
+ ULONG Index;
+ PXENBUS_PDO_REVISION Revision;
Type = REG_SZ;
- Index = Pdo->Count - 1;
+ Index = ARRAYSIZE(PdoRevision) - 1;
+ Revision = &PdoRevision[Index];
status = RtlStringCbPrintfW(Buffer,
Id.MaximumLength,
L"XENBUS\\VEN_%hs&DEV_%hs&REV_%08X",
__PdoGetVendorName(Pdo),
__PdoGetName(Pdo),
- Pdo->Revision[Index]);
+ Revision->Number);
ASSERT(NT_SUCCESS(status));
Buffer += wcslen(Buffer);
Type = REG_MULTI_SZ;
Length = Id.MaximumLength;
- for (Index = 0; Index < Pdo->Count; Index++) {
- status = RtlStringCbPrintfW(Buffer,
- Length,
- L"XENBUS\\VEN_%hs&DEV_%hs&REV_%08X",
- __PdoGetVendorName(Pdo),
- __PdoGetName(Pdo),
- Pdo->Revision[Index]);
+ for (Index = 0; Index < ARRAYSIZE(PdoRevision); Index++) {
+ PXENBUS_PDO_REVISION Revision = &PdoRevision[Index];
+
+ status = RtlStringCbPrintfW(Buffer,
+ Length,
+ L"XENBUS\\VEN_%hs&DEV_%hs&REV_%08X",
+ __PdoGetVendorName(Pdo),
+ __PdoGetName(Pdo),
+ Revision->Number);
ASSERT(NT_SUCCESS(status));
Buffer += wcslen(Buffer);
__PdoSetRemovable(Pdo);
__PdoSetEjectable(Pdo);
- status = PdoSetRevisions(Pdo);
- if (!NT_SUCCESS(status))
- goto fail5;
-
status = BusInitialize(Pdo, &Pdo->BusInterface);
if (!NT_SUCCESS(status))
- goto fail6;
+ goto fail5;
status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
ASSERT(NT_SUCCESS(status));
ASSERT(Pdo->SuspendInterface.Interface.Context != NULL);
- Info("%p (%s: Highest Revision = %08X)\n",
+ Info("%p (%s)\n",
PhysicalDeviceObject,
- __PdoGetName(Pdo),
- Pdo->Revision[Pdo->Count - 1]);
+ __PdoGetName(Pdo));
+
+ PdoDumpRevisions(Pdo);
Dx->Pdo = Pdo;
PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
-fail6:
- Error("fail6\n");
-
- __PdoFree(Pdo->Revision);
- Pdo->Revision = NULL;
- Pdo->Count = 0;
-
fail5:
Error("fail5\n");
+ Pdo->Ejectable = FALSE;
Pdo->Removable = FALSE;
ThreadAlert(Pdo->DevicePowerThread);
BusTeardown(&Pdo->BusInterface);
- __PdoFree(Pdo->Revision);
- Pdo->Revision = NULL;
- Pdo->Count = 0;
-
Pdo->Ejectable = FALSE;
Pdo->Removable = FALSE;