From: Paul Durrant Date: Tue, 24 Nov 2015 15:41:10 +0000 (+0000) Subject: Publish distribution information to xenstore X-Git-Tag: 8.1.0-rc4^0 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=931364c292e64c1872a468f30c1db763c96a0767;p=pvdrivers%2Fwin%2Fxennet.git Publish distribution information to xenstore My recent patch series to Xen added a documented path and format for publishing information about PV driver distributions to xenstore. This patch adds code to populate the documented path (should it exist) with information about the XENNET driver package. Suggested-by: Owen Smith Signed-off-by: Paul Durrant --- diff --git a/include/store_interface.h b/include/store_interface.h new file mode 100644 index 0000000..f2b2147 --- /dev/null +++ b/include/store_interface.h @@ -0,0 +1,347 @@ +/* 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. + */ + +/*! \file store_interface.h + \brief XENBUS STORE Interface + + This interface provides access to XenStore +*/ + +#ifndef _XENBUS_STORE_INTERFACE_H +#define _XENBUS_STORE_INTERFACE_H + +#ifndef _WINDLL + +/*! \typedef XENBUS_STORE_TRANSACTION + \brief XenStore transaction handle +*/ +typedef struct _XENBUS_STORE_TRANSACTION XENBUS_STORE_TRANSACTION, *PXENBUS_STORE_TRANSACTION; + +/*! \typedef XENBUS_STORE_WATCH + \brief XenStore watch handle +*/ +typedef struct _XENBUS_STORE_WATCH XENBUS_STORE_WATCH, *PXENBUS_STORE_WATCH; + +/*! \typedef XENBUS_STORE_PERMISSION_MASK + \brief Bitmask of XenStore key permissions +*/ +typedef enum _XENBUS_STORE_PERMISSION_MASK { + XENBUS_STORE_PERM_NONE = 0, + XENBUS_STORE_PERM_READ = 1, + XENBUS_STORE_PERM_WRITE = 2, +} XENBUS_STORE_PERMISSION_MASK; + +/*! \typedef XENBUS_STORE_PERMISSION + \brief XenStore key permissions entry for a single domain +*/ +typedef struct _XENBUS_STORE_PERMISSION { + USHORT Domain; + XENBUS_STORE_PERMISSION_MASK Mask; +} XENBUS_STORE_PERMISSION, *PXENBUS_STORE_PERMISSION; + +/*! \typedef XENBUS_STORE_ACQUIRE + \brief Acquire a reference to the STORE interface + + \param Interface The interface header +*/ +typedef NTSTATUS +(*XENBUS_STORE_ACQUIRE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_STORE_RELEASE + \brief Release a reference to the STORE interface + + \param Interface The interface header +*/ +typedef VOID +(*XENBUS_STORE_RELEASE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_STORE_FREE + \brief Free a memory buffer allocated by the STORE interface + + \param Interface The interface header + \param Buffer Pointer to the memory buffer +*/ +typedef VOID +(*XENBUS_STORE_FREE)( + IN PINTERFACE Interface, + IN PCHAR Buffer + ); + +/*! \typedef XENBUS_STORE_READ + \brief Read a value from XenStore + + \param Interface The interface header + \param Transaction The transaction handle (NULL if this read is not + part of a transaction) + \param Prefix An optional prefix for the \a Node + \param Node The concatenation of the \a Prefix and this value specifies + the XenStore key to read + \param A pointer to a pointer that will be initialized with a memory + buffer containing the value read + + The \a Buffer should be freed using \a XENBUS_STORE_FREE +*/ +typedef NTSTATUS +(*XENBUS_STORE_READ)( + IN PINTERFACE Interface, + IN PXENBUS_STORE_TRANSACTION Transaction OPTIONAL, + IN PCHAR Prefix OPTIONAL, + IN PCHAR Node, + OUT PCHAR *Buffer + ); + +/*! \typedef XENBUS_STORE_PRINTF + \brief Write a value to XenStore + + \param Interface The interface header + \param Transaction The transaction handle (NULL if this write is not + part of a transaction) + \param Prefix An optional prefix for the \a Node + \param Node The concatenation of the \a Prefix and this value specifies + the XenStore key to write + \param Format A format specifier + \param ... Additional parameters required by \a Format + + If the \a Node does not exist then it is created +*/ +typedef NTSTATUS +(*XENBUS_STORE_PRINTF)( + IN PINTERFACE Interface, + IN PXENBUS_STORE_TRANSACTION Transaction OPTIONAL, + IN PCHAR Prefix OPTIONAL, + IN PCHAR Node, + IN const CHAR *Format, + ... + ); + +/*! \typedef XENBUS_STORE_REMOVE + \brief Remove a key from XenStore + + \param Interface The interface header + \param Transaction The transaction handle (NULL if this removal is not + part of a transaction) + \param Prefix An optional prefix for the \a Node + \param Node The concatenation of the \a Prefix and this value specifies + the XenStore key to remove +*/ +typedef NTSTATUS +(*XENBUS_STORE_REMOVE)( + IN PINTERFACE Interface, + IN PXENBUS_STORE_TRANSACTION Transaction OPTIONAL, + IN PCHAR Prefix OPTIONAL, + IN PCHAR Node + ); + +/*! \typedef XENBUS_STORE_DIRECTORY + \brief Enumerate all immediate child keys of a XenStore key + + \param Interface The interface header + \param Transaction The transaction handle (NULL if this removal is not + part of a transaction) + \param Prefix An optional prefix for the \a Node + \param Node The concatenation of the \a Prefix and this value specifies + the XenStore key to enumerate + \param A pointer to a pointer that will be initialized with a memory + buffer containing a NUL separated list of key names + + The \a Buffer should be freed using \a XENBUS_STORE_FREE +*/ +typedef NTSTATUS +(*XENBUS_STORE_DIRECTORY)( + IN PINTERFACE Interface, + IN PXENBUS_STORE_TRANSACTION Transaction OPTIONAL, + IN PCHAR Prefix OPTIONAL, + IN PCHAR Node, + OUT PCHAR *Buffer + ); + +/*! \typedef XENBUS_STORE_TRANSACTION_START + \brief Start a XenStore transaction + + \param Interface The interface header + \param Transaction Pointer to a transaction handle to be initialized +*/ +typedef NTSTATUS +(*XENBUS_STORE_TRANSACTION_START)( + IN PINTERFACE Interface, + OUT PXENBUS_STORE_TRANSACTION *Transaction + ); + +/*! \typedef XENBUS_STORE_TRANSACTION_END + \brief End a XenStore transaction + + \param Interface The interface header + \param Transaction The transaction handle + \param Commit Set to TRUE if actions performed within the transaction should + be made visible, or FALSE if they should not be + + If \a Commit is TRUE and the transaction to found to clash then + STATUS_RETRY will be returned +*/ +typedef NTSTATUS +(*XENBUS_STORE_TRANSACTION_END)( + IN PINTERFACE Interface, + IN PXENBUS_STORE_TRANSACTION Transaction, + IN BOOLEAN Commit + ); + +/*! \typedef XENBUS_STORE_WATCH_ADD + \brief Add a XenStore watch + + \param Interface The interface header + \param Prefix An optional prefix for the \a Node + \param Node The concatenation of the \a Prefix and this value specifies + the XenStore key to watch + \param Event A pointer to an event object to be signalled when the + watch fires + \param Watch A pointer to a watch handle to be initialized +*/ +typedef NTSTATUS +(*XENBUS_STORE_WATCH_ADD)( + IN PINTERFACE Interface, + IN PCHAR Prefix OPTIONAL, + IN PCHAR Node, + IN PKEVENT Event, + OUT PXENBUS_STORE_WATCH *Watch + ); + +/*! \typedef XENBUS_STORE_WATCH_REMOVE + \brief Remove a XenStore watch + + \param Interface The interface header + \param Watch The watch handle +*/ +typedef NTSTATUS +(*XENBUS_STORE_WATCH_REMOVE)( + IN PINTERFACE Interface, + IN PXENBUS_STORE_WATCH Watch + ); + +/*! \typedef XENBUS_STORE_POLL + \brief Poll for XenStore activity + + \param Interface The interface header + + If it is necessary to spin at DISPATCH_LEVEL waiting for XenStore + activity then this will block the normal STORE interface DPC so this + method must be regularly invoked during the spin loop to check for + XenStore activity +*/ +typedef VOID +(*XENBUS_STORE_POLL)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_STORE_PERMISSIONS_SET + \brief Set permissions for a XenStore key + + \param Interface The interface header + \param Transaction The transaction handle (NULL if this is not + part of a transaction) + \param Prefix An optional prefix for the \a Node + \param Node The concatenation of the \a Prefix and this value specifies + the XenStore key to set permissions of + \param Permissions An array of permissions to set + \param NumberPermissions Number of elements in the \a Permissions array +*/ +typedef NTSTATUS +(*XENBUS_STORE_PERMISSIONS_SET)( + IN PINTERFACE Interface, + IN PXENBUS_STORE_TRANSACTION Transaction OPTIONAL, + IN PCHAR Prefix OPTIONAL, + IN PCHAR Node, + IN PXENBUS_STORE_PERMISSION Permissions, + IN ULONG NumberPermissions + ); + +// {86824C3B-D34E-4753-B281-2F1E3AD214D7} +DEFINE_GUID(GUID_XENBUS_STORE_INTERFACE, +0x86824c3b, 0xd34e, 0x4753, 0xb2, 0x81, 0x2f, 0x1e, 0x3a, 0xd2, 0x14, 0xd7); + +/*! \struct _XENBUS_STORE_INTERFACE_V1 + \brief STORE interface version 1 + \ingroup interfaces +*/ +struct _XENBUS_STORE_INTERFACE_V1 { + INTERFACE Interface; + XENBUS_STORE_ACQUIRE StoreAcquire; + XENBUS_STORE_RELEASE StoreRelease; + XENBUS_STORE_FREE StoreFree; + XENBUS_STORE_READ StoreRead; + XENBUS_STORE_PRINTF StorePrintf; + XENBUS_STORE_REMOVE StoreRemove; + XENBUS_STORE_DIRECTORY StoreDirectory; + XENBUS_STORE_TRANSACTION_START StoreTransactionStart; + XENBUS_STORE_TRANSACTION_END StoreTransactionEnd; + XENBUS_STORE_WATCH_ADD StoreWatchAdd; + XENBUS_STORE_WATCH_REMOVE StoreWatchRemove; + XENBUS_STORE_POLL StorePoll; +}; + +/*! \struct _XENBUS_STORE_INTERFACE_V2 + \brief STORE interface version 2 + \ingroup interfaces +*/ +struct _XENBUS_STORE_INTERFACE_V2 { + INTERFACE Interface; + XENBUS_STORE_ACQUIRE StoreAcquire; + XENBUS_STORE_RELEASE StoreRelease; + XENBUS_STORE_FREE StoreFree; + XENBUS_STORE_READ StoreRead; + XENBUS_STORE_PRINTF StorePrintf; + XENBUS_STORE_PERMISSIONS_SET StorePermissionsSet; + XENBUS_STORE_REMOVE StoreRemove; + XENBUS_STORE_DIRECTORY StoreDirectory; + XENBUS_STORE_TRANSACTION_START StoreTransactionStart; + XENBUS_STORE_TRANSACTION_END StoreTransactionEnd; + XENBUS_STORE_WATCH_ADD StoreWatchAdd; + XENBUS_STORE_WATCH_REMOVE StoreWatchRemove; + XENBUS_STORE_POLL StorePoll; +}; + +typedef struct _XENBUS_STORE_INTERFACE_V2 XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE; + +/*! \def XENBUS_STORE + \brief Macro at assist in method invocation +*/ +#define XENBUS_STORE(_Method, _Interface, ...) \ + (_Interface)->Store ## _Method((PINTERFACE)(_Interface), __VA_ARGS__) + +#endif // _WINDLL + +#define XENBUS_STORE_INTERFACE_VERSION_MIN 1 +#define XENBUS_STORE_INTERFACE_VERSION_MAX 2 + +#endif // _XENBUS_STORE_INTERFACE_H diff --git a/include/suspend_interface.h b/include/suspend_interface.h new file mode 100644 index 0000000..9ef386b --- /dev/null +++ b/include/suspend_interface.h @@ -0,0 +1,176 @@ +/* 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. + */ + +/*! \file suspend_interface.h + \brief XENBUS SUSPEND Interface + + This interface provides primitives to handle VM suspend/resume +*/ + +#ifndef _XENBUS_SUSPEND_INTERFACE_H +#define _XENBUS_SUSPEND_INTERFACE_H + +#ifndef _WINDLL + +/*! \enum _XENBUS_SUSPEND_CALLBACK_TYPE + \brief Suspend callback type to be registered +*/ +typedef enum _XENBUS_SUSPEND_CALLBACK_TYPE { + SUSPEND_CALLBACK_TYPE_INVALID = 0, + SUSPEND_CALLBACK_EARLY, /*!< Early */ + SUSPEND_CALLBACK_LATE /*!< Late */ +} XENBUS_SUSPEND_CALLBACK_TYPE, *PXENBUS_SUSPEND_CALLBACK_TYPE; + +/*! \typedef XENBUS_SUSPEND_CALLBACK + \brief Suspend callback handle +*/ +typedef struct _XENBUS_SUSPEND_CALLBACK XENBUS_SUSPEND_CALLBACK, *PXENBUS_SUSPEND_CALLBACK; + +/*! \typedef XENBUS_SUSPEND_ACQUIRE + \brief Acquire a reference to the SUSPEND interface + + \param Interface The interface header +*/ +typedef NTSTATUS +(*XENBUS_SUSPEND_ACQUIRE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_SUSPEND_RELEASE + \brief Release a reference to the SUSPEND interface + + \param Interface The interface header +*/ +typedef VOID +(*XENBUS_SUSPEND_RELEASE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_SUSPEND_FUNCTION + \brief Suspend callback function + + \param Argument Context \a Argument supplied to \a XENBUS_SUSPEND_REGISTER + + Suspend callback functions are always invoked on one vCPU with all other + vCPUs corralled at the same IRQL as the callback. \a Early callback + functions are always invoked with IRQL == HIGH_LEVEL and \a Late callback + functions are always invoked with IRQL == DISPATCH_LEVEL +*/ +typedef VOID +(*XENBUS_SUSPEND_FUNCTION)( + IN PVOID Argument + ); + +/*! \typedef XENBUS_SUSPEND_REGISTER + \brief Register a suspend callback function + + \param Interface The interface header + \param Type The type of callback function to register + \param Function The callback function + \param Argument An optional context argument passed to the callback + \param Callback A pointer to a callback handle to be initialized +*/ +typedef NTSTATUS +(*XENBUS_SUSPEND_REGISTER)( + IN PINTERFACE Interface, + IN XENBUS_SUSPEND_CALLBACK_TYPE Type, + IN XENBUS_SUSPEND_FUNCTION Function, + IN PVOID Argument OPTIONAL, + OUT PXENBUS_SUSPEND_CALLBACK *Callback + ); + +/*! \typedef XENBUS_SUSPEND_DEREGISTER + \brief Deregister a suspend callback function + + \param Interface The interface header + \param Callback The callback handle +*/ +typedef VOID +(*XENBUS_SUSPEND_DEREGISTER)( + IN PINTERFACE Interface, + IN PXENBUS_SUSPEND_CALLBACK Callback + ); + +/*! \typedef XENBUS_SUSPEND_TRIGGER + \brief Trigger a VM suspend + + \param Interface The interface header + + This method must always be invoked with IRQL == PASSIVE_LEVEL +*/ +typedef NTSTATUS +(*XENBUS_SUSPEND_TRIGGER)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_SUSPEND_GET_COUNT + \brief Get the number of VM suspends that have occurred since boot + + \param Interface The interface header + \return The number of VM suspends +*/ +typedef ULONG +(*XENBUS_SUSPEND_GET_COUNT)( + IN PINTERFACE Interface + ); + +// {0554F2AF-B510-4C71-AC03-1C503E394238} +DEFINE_GUID(GUID_XENBUS_SUSPEND_INTERFACE, +0x554f2af, 0xb510, 0x4c71, 0xac, 0x3, 0x1c, 0x50, 0x3e, 0x39, 0x42, 0x38); + +/*! \struct _XENBUS_SUSPEND_INTERFACE_V1 + \brief SUSPEND interface version 1 + \ingroup interfaces +*/ +struct _XENBUS_SUSPEND_INTERFACE_V1 { + INTERFACE Interface; + XENBUS_SUSPEND_ACQUIRE Acquire; + XENBUS_SUSPEND_RELEASE Release; + XENBUS_SUSPEND_REGISTER Register; + XENBUS_SUSPEND_DEREGISTER Deregister; + XENBUS_SUSPEND_TRIGGER Trigger; + XENBUS_SUSPEND_GET_COUNT GetCount; +}; + +typedef struct _XENBUS_SUSPEND_INTERFACE_V1 XENBUS_SUSPEND_INTERFACE, *PXENBUS_SUSPEND_INTERFACE; + +/*! \def XENBUS_SUSPEND + \brief Macro at assist in method invocation +*/ +#define XENBUS_SUSPEND(_Method, _Interface, ...) \ + (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__) + +#endif // _WINDLL + +#define XENBUS_SUSPEND_INTERFACE_VERSION_MIN 1 +#define XENBUS_SUSPEND_INTERFACE_VERSION_MAX 1 + +#endif // _XENBUS_SUSPEND_INTERFACE_H diff --git a/src/xennet.inf b/src/xennet.inf index 7e9d9e6..bbec43f 100644 --- a/src/xennet.inf +++ b/src/xennet.inf @@ -61,9 +61,9 @@ xennet_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll ; DisplayName Section DeviceID ; ----------- ------- -------- -%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_NET&REV_08000002 -%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0001&DEV_NET&REV_08000002 -%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0002&DEV_NET&REV_08000002 +%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_NET&REV_08000005 +%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0001&DEV_NET&REV_08000005 +%XenNetDesc% =XenNet_Inst, XENVIF\VEN_@VENDOR_PREFIX@0002&DEV_NET&REV_08000005 [XenNet_Inst] Characteristics=0x84 diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c index a1460c7..20aabee 100644 --- a/src/xennet/adapter.c +++ b/src/xennet/adapter.c @@ -32,36 +32,48 @@ #define INITGUID 1 #include +#include #include #include #include #include +#include +#include #include "adapter.h" #include "transmitter.h" #include "receiver.h" +#include "util.h" #include "dbg_print.h" #include "assert.h" +#define MAXNAMELEN 128 + struct _XENNET_ADAPTER { - XENVIF_VIF_INTERFACE VifInterface; - XENBUS_CACHE_INTERFACE CacheInterface; + XENVIF_VIF_INTERFACE VifInterface; + XENBUS_CACHE_INTERFACE CacheInterface; + XENBUS_STORE_INTERFACE StoreInterface; + XENBUS_SUSPEND_INTERFACE SuspendInterface; + + PXENBUS_SUSPEND_CALLBACK SuspendCallbackLate; - ULONG MaximumFrameSize; - ULONG CurrentLookahead; + ULONG MaximumFrameSize; + ULONG CurrentLookahead; - NDIS_HANDLE NdisAdapterHandle; - NDIS_HANDLE NdisDmaHandle; - NDIS_PNP_CAPABILITIES Capabilities; - NDIS_OFFLOAD Offload; - PROPERTIES Properties; + NDIS_HANDLE NdisAdapterHandle; + NDIS_HANDLE NdisDmaHandle; + NDIS_PNP_CAPABILITIES Capabilities; + NDIS_OFFLOAD Offload; + PROPERTIES Properties; - PXENNET_RECEIVER Receiver; - PXENNET_TRANSMITTER Transmitter; - BOOLEAN Enabled; + PXENNET_RECEIVER Receiver; + PXENNET_TRANSMITTER Transmitter; + BOOLEAN Enabled; }; +static LONG AdapterCount; + static NDIS_OID XennetSupportedOids[] = { OID_GEN_SUPPORTED_LIST, @@ -2151,6 +2163,395 @@ AdapterSetOffloadAttributes( return ndisStatus; } +static FORCEINLINE PVOID +__AdapterAllocate( + IN ULONG Length + ) +{ + return __AllocateNonPagedPoolWithTag(Length, ADAPTER_POOL_TAG); +} + +static FORCEINLINE VOID +__AdapterFree( + IN PVOID Buffer + ) +{ + __FreePoolWithTag(Buffer, ADAPTER_POOL_TAG); +} + +static FORCEINLINE PANSI_STRING +__AdapterMultiSzToUpcaseAnsi( + IN PCHAR Buffer + ) +{ + PANSI_STRING Ansi; + LONG Index; + LONG Count; + NTSTATUS status; + + Index = 0; + Count = 0; + for (;;) { + if (Buffer[Index] == '\0') { + Count++; + Index++; + + // Check for double NUL + if (Buffer[Index] == '\0') + break; + } else { + Buffer[Index] = (CHAR)toupper(Buffer[Index]); + Index++; + } + } + + Ansi = __AdapterAllocate(sizeof (ANSI_STRING) * (Count + 1)); + + status = STATUS_NO_MEMORY; + if (Ansi == NULL) + goto fail1; + + for (Index = 0; Index < Count; Index++) { + ULONG Length; + + Length = (ULONG)strlen(Buffer); + Ansi[Index].MaximumLength = (USHORT)(Length + 1); + Ansi[Index].Buffer = __AdapterAllocate(Ansi[Index].MaximumLength); + + status = STATUS_NO_MEMORY; + if (Ansi[Index].Buffer == NULL) + goto fail2; + + RtlCopyMemory(Ansi[Index].Buffer, Buffer, Length); + Ansi[Index].Length = (USHORT)Length; + + Buffer += Length + 1; + } + + return Ansi; + +fail2: + Error("fail2\n"); + + while (--Index >= 0) + __AdapterFree(Ansi[Index].Buffer); + + __AdapterFree(Ansi); + +fail1: + Error("fail1 (%08x)\n", status); + + return NULL; +} + +static FORCEINLINE VOID +__AdapterFreeAnsi( + IN PANSI_STRING Ansi + ) +{ + ULONG Index; + + for (Index = 0; Ansi[Index].Buffer != NULL; Index++) + __AdapterFree(Ansi[Index].Buffer); + + __AdapterFree(Ansi); +} + +static FORCEINLINE BOOLEAN +__AdapterMatchDistribution( + IN PXENNET_ADAPTER Adapter, + IN PCHAR Buffer + ) +{ + PCHAR Vendor; + PCHAR Product; + PCHAR Context; + const CHAR *Text; + BOOLEAN Match; + ULONG Index; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Adapter); + + status = STATUS_INVALID_PARAMETER; + + Vendor = __strtok_r(Buffer, " ", &Context); + if (Vendor == NULL) + goto fail1; + + Product = __strtok_r(NULL, " ", &Context); + if (Product == NULL) + goto fail2; + + Match = TRUE; + + Text = VENDOR_NAME_STR; + + for (Index = 0; Text[Index] != 0; Index++) { + if (!isalnum((UCHAR)Text[Index])) { + if (Vendor[Index] != '_') { + Match = FALSE; + break; + } + } else { + if (Vendor[Index] != Text[Index]) { + Match = FALSE; + break; + } + } + } + + Text = "XENNET"; + + if (_stricmp(Product, Text) != 0) + Match = FALSE; + + return Match; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return FALSE; +} + +static FORCEINLINE VOID +__AdapterClearDistribution( + IN PXENNET_ADAPTER Adapter + ) +{ + PCHAR Buffer; + PANSI_STRING Distributions; + ULONG Index; + NTSTATUS status; + + Trace("====>\n"); + + status = XENBUS_STORE(Directory, + &Adapter->StoreInterface, + NULL, + NULL, + "drivers", + &Buffer); + if (NT_SUCCESS(status)) { + Distributions = __AdapterMultiSzToUpcaseAnsi(Buffer); + + XENBUS_STORE(Free, + &Adapter->StoreInterface, + Buffer); + } else { + Distributions = NULL; + } + + if (Distributions == NULL) + goto done; + + for (Index = 0; Distributions[Index].Buffer != NULL; Index++) { + PANSI_STRING Distribution = &Distributions[Index]; + + status = XENBUS_STORE(Read, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution->Buffer, + &Buffer); + if (!NT_SUCCESS(status)) + continue; + + if (__AdapterMatchDistribution(Adapter, Buffer)) + (VOID) XENBUS_STORE(Remove, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution->Buffer); + + XENBUS_STORE(Free, + &Adapter->StoreInterface, + Buffer); + } + + __AdapterFreeAnsi(Distributions); + +done: + Trace("<====\n"); +} + +#define MAXIMUM_INDEX 255 + +static FORCEINLINE NTSTATUS +__AdapterSetDistribution( + IN PXENNET_ADAPTER Adapter + ) +{ + ULONG Index; + CHAR Distribution[MAXNAMELEN]; + CHAR Vendor[MAXNAMELEN]; + const CHAR *Product; + NTSTATUS status; + + Trace("====>\n"); + + Index = 0; + while (Index <= MAXIMUM_INDEX) { + PCHAR Buffer; + + status = RtlStringCbPrintfA(Distribution, + MAXNAMELEN, + "%u", + Index); + ASSERT(NT_SUCCESS(status)); + + status = XENBUS_STORE(Read, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution, + &Buffer); + if (!NT_SUCCESS(status)) { + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + goto update; + + goto fail1; + } + + XENBUS_STORE(Free, + &Adapter->StoreInterface, + Buffer); + + Index++; + } + + status = STATUS_UNSUCCESSFUL; + goto fail2; + +update: + status = RtlStringCbPrintfA(Vendor, + MAXNAMELEN, + "%s", + VENDOR_NAME_STR); + ASSERT(NT_SUCCESS(status)); + + for (Index = 0; Vendor[Index] != '\0'; Index++) + if (!isalnum((UCHAR)Vendor[Index])) + Vendor[Index] = '_'; + + Product = "XENNET"; + +#if DBG +#define ATTRIBUTES "(DEBUG)" +#else +#define ATTRIBUTES "" +#endif + + (VOID) XENBUS_STORE(Printf, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution, + "%s %s %u.%u.%u %s", + Vendor, + Product, + MAJOR_VERSION, + MINOR_VERSION, + MICRO_VERSION, + ATTRIBUTES + ); + +#undef ATTRIBUTES + + Trace("<====\n"); + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static DECLSPEC_NOINLINE VOID +AdapterSuspendCallbackLate( + IN PVOID Argument + ) +{ + PXENNET_ADAPTER Adapter = Argument; + + (VOID) __AdapterSetDistribution(Adapter); +} + +static NTSTATUS +AdapterSetDistribution( + IN PXENNET_ADAPTER Adapter + ) +{ + LONG Count; + NTSTATUS status; + + Trace("====>\n"); + + Count = InterlockedIncrement(&AdapterCount); + ASSERT(Count != 0); + + if (Count != 1) + goto done; + + status = __AdapterSetDistribution(Adapter); + if (!NT_SUCCESS(status)) + goto fail1; + + status = XENBUS_SUSPEND(Register, + &Adapter->SuspendInterface, + SUSPEND_CALLBACK_LATE, + AdapterSuspendCallbackLate, + Adapter, + &Adapter->SuspendCallbackLate); + if (!NT_SUCCESS(status)) + goto fail2; + +done: + Trace("<====\n"); + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + + __AdapterClearDistribution(Adapter); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static VOID +AdapterClearDistribution( + IN PXENNET_ADAPTER Adapter + ) +{ + LONG Count; + + Trace("====>\n"); + + Count = InterlockedDecrement(&AdapterCount); + + if (Count != 0) + goto done; + + XENBUS_SUSPEND(Deregister, + &Adapter->SuspendInterface, + Adapter->SuspendCallbackLate); + Adapter->SuspendCallbackLate = NULL; + + __AdapterClearDistribution(Adapter); + +done: + Trace("<====\n"); +} + NDIS_STATUS AdapterInitialize( IN NDIS_HANDLE Handle, @@ -2162,9 +2563,7 @@ AdapterInitialize( PDEVICE_OBJECT DeviceObject; NDIS_SG_DMA_DESCRIPTION Dma; - *Adapter = ExAllocatePoolWithTag(NonPagedPool, - sizeof(XENNET_ADAPTER), - ADAPTER_POOL_TAG); + *Adapter = __AdapterAllocate(sizeof (XENNET_ADAPTER)); ndisStatus = NDIS_STATUS_RESOURCES; if (*Adapter == NULL) @@ -2199,41 +2598,71 @@ AdapterInitialize( if (!NT_SUCCESS(status)) goto fail3; + status = __QueryInterface(DeviceObject, + &GUID_XENBUS_STORE_INTERFACE, + XENBUS_STORE_INTERFACE_VERSION_MAX, + (PINTERFACE)&(*Adapter)->StoreInterface, + sizeof(XENBUS_STORE_INTERFACE), + FALSE); + if (!NT_SUCCESS(status)) + goto fail4; + + status = __QueryInterface(DeviceObject, + &GUID_XENBUS_SUSPEND_INTERFACE, + XENBUS_SUSPEND_INTERFACE_VERSION_MAX, + (PINTERFACE)&(*Adapter)->SuspendInterface, + sizeof(XENBUS_SUSPEND_INTERFACE), + FALSE); + if (!NT_SUCCESS(status)) + goto fail5; + status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface); if (!NT_SUCCESS(status)) - goto fail4; + goto fail6; status = XENBUS_CACHE(Acquire, &(*Adapter)->CacheInterface); if (!NT_SUCCESS(status)) - goto fail5; + goto fail7; + + status = XENBUS_STORE(Acquire, + &(*Adapter)->StoreInterface); + if (!NT_SUCCESS(status)) + goto fail8; + + status = XENBUS_SUSPEND(Acquire, + &(*Adapter)->SuspendInterface); + if (!NT_SUCCESS(status)) + goto fail9; + + (VOID) AdapterSetDistribution(*Adapter); (*Adapter)->NdisAdapterHandle = Handle; ndisStatus = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail6; + goto fail10; ndisStatus = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail7; + goto fail11; ndisStatus = AdapterGetAdvancedSettings(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail8; + goto fail12; ndisStatus = AdapterSetRegistrationAttributes(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail9; + goto fail13; ndisStatus = AdapterSetGeneralAttributes(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail10; + goto fail14; ndisStatus = AdapterSetOffloadAttributes(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail11; + goto fail15; RtlZeroMemory(&Dma, sizeof(NDIS_SG_DMA_DESCRIPTION)); Dma.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; @@ -2252,35 +2681,57 @@ AdapterInitialize( ndisStatus = AdapterEnable(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail12; + goto fail16; return NDIS_STATUS_SUCCESS; -fail12: +fail16: if ((*Adapter)->NdisDmaHandle) NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle); (*Adapter)->NdisDmaHandle = NULL; -fail11: -fail10: -fail9: -fail8: + +fail15: +fail14: +fail13: +fail12: ReceiverTeardown((*Adapter)->Receiver); (*Adapter)->Receiver = NULL; -fail7: +fail11: + TransmitterTeardown((*Adapter)->Transmitter); (*Adapter)->Transmitter = NULL; -fail6: + +fail10: (*Adapter)->NdisAdapterHandle = NULL; + AdapterClearDistribution(*Adapter); + + XENBUS_SUSPEND(Release, &(*Adapter)->SuspendInterface); + +fail9: + XENBUS_STORE(Release, &(*Adapter)->StoreInterface); + +fail8: XENBUS_CACHE(Release, &(*Adapter)->CacheInterface); -fail5: + +fail7: XENVIF_VIF(Release, &(*Adapter)->VifInterface); + +fail6: + RtlZeroMemory(&(*Adapter)->SuspendInterface, sizeof(XENBUS_SUSPEND_INTERFACE)); + +fail5: + RtlZeroMemory(&(*Adapter)->StoreInterface, sizeof(XENBUS_STORE_INTERFACE)); + fail4: RtlZeroMemory(&(*Adapter)->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE)); + fail3: RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE)); + fail2: - ExFreePoolWithTag(*Adapter, ADAPTER_POOL_TAG); + __AdapterFree(*Adapter); + fail1: return ndisStatus; } @@ -2300,11 +2751,17 @@ AdapterTeardown( NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle); Adapter->NdisDmaHandle = NULL; - XENBUS_CACHE(Release, &Adapter->CacheInterface); - RtlZeroMemory(&Adapter->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE)); + AdapterClearDistribution(Adapter); + XENBUS_SUSPEND(Release, &Adapter->SuspendInterface); + XENBUS_STORE(Release, &Adapter->StoreInterface); + XENBUS_CACHE(Release, &Adapter->CacheInterface); XENVIF_VIF(Release, &Adapter->VifInterface); + + RtlZeroMemory(&Adapter->SuspendInterface, sizeof(XENBUS_SUSPEND_INTERFACE)); + RtlZeroMemory(&Adapter->StoreInterface, sizeof(XENBUS_STORE_INTERFACE)); + RtlZeroMemory(&Adapter->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE)); RtlZeroMemory(&Adapter->VifInterface, sizeof(XENVIF_VIF_INTERFACE)); - ExFreePoolWithTag(Adapter, ADAPTER_POOL_TAG); + __AdapterFree(Adapter); } diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj index 8c1862e..e78e41b 100644 --- a/vs2012/xennet/xennet.vcxproj +++ b/vs2012/xennet/xennet.vcxproj @@ -40,7 +40,7 @@ false - $(DDK_LIB_PATH)\ndis.lib;%(AdditionalDependencies) + $(DDK_LIB_PATH)\ndis.lib;$(DDK_LIB_PATH)/libcntpr.lib;%(AdditionalDependencies) false diff --git a/vs2013/xennet/xennet.vcxproj b/vs2013/xennet/xennet.vcxproj index 0aa30a6..4e81fc4 100644 --- a/vs2013/xennet/xennet.vcxproj +++ b/vs2013/xennet/xennet.vcxproj @@ -11,43 +11,7 @@ DbgengKernelDebugger - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - v120 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - - WindowsKernelModeDriver8.1 - - + WindowsKernelModeDriver8.1 @@ -72,7 +36,7 @@ false - $(DDK_LIB_PATH)\ndis.lib;%(AdditionalDependencies) + $(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)\ndis.lib;%(AdditionalDependencies) false