[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH for 8.1] Make sure XENBUS interfaces are released when going into S4
Because a transition into and out of S4 means a new domain is built, it's crucial that all XENBUS interfaces are released (so that things like event channels, grant tables and the xenstore ring get re-constructed). This patch fixes code paths where this was not being done. It also adds some more logging during AdapterEnable/Disable and when moving between D0 and D3. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- src/xennet/adapter.c | 2719 +++++++++++++++++++++++----------------------- src/xennet/adapter.h | 2 +- src/xennet/miniport.c | 21 +- src/xennet/receiver.c | 18 + src/xennet/receiver.h | 10 + src/xennet/transmitter.c | 63 +- src/xennet/transmitter.h | 10 + 7 files changed, 1471 insertions(+), 1372 deletions(-) diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c index f9b3cf1..2c35636 100644 --- a/src/xennet/adapter.c +++ b/src/xennet/adapter.c @@ -1074,1576 +1074,1671 @@ AdapterGetReceiver( return Adapter->Receiver; } -NDIS_STATUS -AdapterEnable( - IN PXENNET_ADAPTER Adapter +static FORCEINLINE PVOID +__AdapterAllocate( + IN ULONG Length ) { - NTSTATUS status; - - if (Adapter->Enabled) - return NDIS_STATUS_SUCCESS; - - status = XENVIF_VIF(Enable, - &Adapter->VifInterface, - AdapterVifCallback, - Adapter); - if (!NT_SUCCESS(status)) - goto fail1; - - Adapter->Enabled = TRUE; - - return NDIS_STATUS_SUCCESS; + return __AllocateNonPagedPoolWithTag(Length, ADAPTER_POOL_TAG); +} -fail1: - return NDIS_STATUS_FAILURE; +static FORCEINLINE VOID +__AdapterFree( + IN PVOID Buffer + ) +{ + __FreePoolWithTag(Buffer, ADAPTER_POOL_TAG); } -BOOLEAN -AdapterDisable( - IN PXENNET_ADAPTER Adapter +static FORCEINLINE PANSI_STRING +__AdapterMultiSzToUpcaseAnsi( + IN PCHAR Buffer ) { - if (!Adapter->Enabled) - return FALSE; + PANSI_STRING Ansi; + LONG Index; + LONG Count; + NTSTATUS status; - XENVIF_VIF(Disable, - &Adapter->VifInterface); + Index = 0; + Count = 0; + for (;;) { + if (Buffer[Index] == '\0') { + Count++; + Index++; - AdapterMediaStateChange(Adapter); + // Check for double NUL + if (Buffer[Index] == '\0') + break; + } else { + Buffer[Index] = (CHAR)toupper(Buffer[Index]); + Index++; + } + } - Adapter->Enabled = FALSE; + Ansi = __AdapterAllocate(sizeof (ANSI_STRING) * (Count + 1)); - return TRUE; -} + status = STATUS_NO_MEMORY; + if (Ansi == NULL) + goto fail1; -VOID -AdapterMediaStateChange( - IN PXENNET_ADAPTER Adapter - ) -{ - NDIS_LINK_STATE LinkState; - NDIS_STATUS_INDICATION StatusIndication; + for (Index = 0; Index < Count; Index++) { + ULONG Length; - RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE)); - LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1; - LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - LinkState.Header.Size = sizeof(NDIS_LINK_STATE); + Length = (ULONG)strlen(Buffer); + Ansi[Index].MaximumLength = (USHORT)(Length + 1); + Ansi[Index].Buffer = __AdapterAllocate(Ansi[Index].MaximumLength); - XENVIF_VIF(MacQueryState, - &Adapter->VifInterface, - &LinkState.MediaConnectState, - &LinkState.RcvLinkSpeed, - &LinkState.MediaDuplexState); + status = STATUS_NO_MEMORY; + if (Ansi[Index].Buffer == NULL) + goto fail2; - if (LinkState.MediaConnectState == MediaConnectStateUnknown) { - Info("LINK: STATE UNKNOWN\n"); - } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) { - Info("LINK: DOWN\n"); - } else { - ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected); + RtlCopyMemory(Ansi[Index].Buffer, Buffer, Length); + Ansi[Index].Length = (USHORT)Length; - if (LinkState.MediaDuplexState == MediaDuplexStateHalf) - Info("LINK: UP: SPEED=%u DUPLEX=HALF\n", LinkState.RcvLinkSpeed); - else if (LinkState.MediaDuplexState == MediaDuplexStateFull) - Info("LINK: UP: SPEED=%u DUPLEX=FULL\n", LinkState.RcvLinkSpeed); - else - Info("LINK: UP: SPEED=%u DUPLEX=UNKNOWN\n", LinkState.RcvLinkSpeed); + Buffer += Length + 1; } - LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed; + return Ansi; - RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION)); - StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; - StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; - StatusIndication.Header.Size = sizeof (NDIS_STATUS_INDICATION); +fail2: + Error("fail2\n"); - StatusIndication.SourceHandle = Adapter->NdisAdapterHandle; - StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE; - StatusIndication.StatusBuffer = &LinkState; - StatusIndication.StatusBufferSize = sizeof (NDIS_LINK_STATE); + while (--Index >= 0) + __AdapterFree(Ansi[Index].Buffer); - NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication); + __AdapterFree(Ansi); + +fail1: + Error("fail1 (%08x)\n", status); + + return NULL; } -NDIS_STATUS -AdapterSetInformation( - IN PXENNET_ADAPTER Adapter, - IN PNDIS_OID_REQUEST Request +static FORCEINLINE VOID +__AdapterFreeAnsi( + IN PANSI_STRING Ansi ) { - PVOID Buffer; - ULONG BufferLength; - ULONG BytesNeeded; - ULONG BytesRead; - BOOLEAN Warn; - NDIS_STATUS ndisStatus; + ULONG Index; - Buffer = Request->DATA.SET_INFORMATION.InformationBuffer; - BufferLength = Request->DATA.SET_INFORMATION.InformationBufferLength; - BytesNeeded = BytesRead = 0; - Warn = TRUE; - ndisStatus = NDIS_STATUS_SUCCESS; + for (Index = 0; Ansi[Index].Buffer != NULL; Index++) + __AdapterFree(Ansi[Index].Buffer); - switch (Request->DATA.SET_INFORMATION.Oid) { - case OID_PNP_SET_POWER: - BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); - // do nothing - break; + __AdapterFree(Ansi); +} - case OID_GEN_CURRENT_LOOKAHEAD: - BytesNeeded = sizeof(ULONG); - Adapter->CurrentLookahead = Adapter->MaximumFrameSize; - if (BufferLength == BytesNeeded) { - Adapter->CurrentLookahead = *(PULONG)Buffer; - BytesRead = sizeof(ULONG); - } - break; +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; - case OID_GEN_CURRENT_PACKET_FILTER: - BytesNeeded = sizeof(ULONG); - if (BufferLength == BytesNeeded) { - ndisStatus = AdapterSetPacketFilter(Adapter, - (PULONG)Buffer); - BytesRead = sizeof(ULONG); - } - break; + UNREFERENCED_PARAMETER(Adapter); - case OID_802_3_MULTICAST_LIST: - BytesNeeded = ETHERNET_ADDRESS_LENGTH; - if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) { - ndisStatus = AdapterSetMulticastAddresses(Adapter, - Buffer, - BufferLength / ETHERNET_ADDRESS_LENGTH); - if (ndisStatus == NDIS_STATUS_SUCCESS) - BytesRead = BufferLength; - } else { - ndisStatus = NDIS_STATUS_INVALID_LENGTH; - } - break; + status = STATUS_INVALID_PARAMETER; - case OID_OFFLOAD_ENCAPSULATION: - BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION); - if (BufferLength >= BytesNeeded) { - ndisStatus = AdapterGetOffloadEncapsulation(Adapter, - (PNDIS_OFFLOAD_ENCAPSULATION)Buffer); - if (ndisStatus == NDIS_STATUS_SUCCESS) - BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION); - } - break; + Vendor = __strtok_r(Buffer, " ", &Context); + if (Vendor == NULL) + goto fail1; - case OID_TCP_OFFLOAD_PARAMETERS: - BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS); - if (BufferLength >= BytesNeeded) { - ndisStatus = AdapterGetTcpOffloadParameters(Adapter, - (PNDIS_OFFLOAD_PARAMETERS)Buffer); - if (ndisStatus == NDIS_STATUS_SUCCESS) - BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS); - } - break; + Product = __strtok_r(NULL, " ", &Context); + if (Product == NULL) + goto fail2; - case OID_GEN_HD_SPLIT_PARAMETERS: - BytesNeeded = sizeof(NDIS_HD_SPLIT_PARAMETERS); - if (BufferLength >= BytesNeeded) { - ndisStatus = AdapterGetHeaderDataSplitParameters(Adapter, - (PNDIS_HD_SPLIT_PARAMETERS)Buffer); - if (ndisStatus == NDIS_STATUS_SUCCESS) - BytesRead = sizeof(NDIS_HD_SPLIT_PARAMETERS); - } - break; + Match = TRUE; - case OID_GEN_INTERRUPT_MODERATION: - case OID_GEN_MACHINE_NAME: - Warn = FALSE; - /*FALLTHRU*/ - default: - if (Warn) - Warning("UNSUPPORTED OID %08x\n", Request->DATA.QUERY_INFORMATION.Oid); + Text = VENDOR_NAME_STR; - ndisStatus = NDIS_STATUS_NOT_SUPPORTED; - break; + 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; + } + } } - Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded; - if (ndisStatus == NDIS_STATUS_SUCCESS) - Request->DATA.SET_INFORMATION.BytesRead = BytesRead; + Text = "XENNET"; - return ndisStatus; -} + if (_stricmp(Product, Text) != 0) + Match = FALSE; -static FORCEINLINE NDIS_STATUS -__CopyBuffer( - IN PVOID Destination, - IN ULONG DestinationLength, - IN PVOID Source, - IN ULONG SourceLength, - OUT PULONG CopyLength - ) -{ - *CopyLength = __min(SourceLength, DestinationLength); - RtlCopyMemory(Destination, Source, *CopyLength); + return Match; - return (DestinationLength >= SourceLength) ? - NDIS_STATUS_SUCCESS : - NDIS_STATUS_BUFFER_TOO_SHORT; -} +fail2: + Error("fail2\n"); -static FORCEINLINE NDIS_STATUS -__SetUlong( - IN PVOID Destination, - IN ULONG DestinationLength, - IN ULONG Source, - OUT PULONG CopyLength - ) -{ - return __CopyBuffer(Destination, - DestinationLength & ~3, - &Source, - sizeof (ULONG), - CopyLength); +fail1: + Error("fail1 (%08x)\n", status); + + return FALSE; } -static FORCEINLINE NDIS_STATUS -__SetUlong64( - IN PVOID Destination, - IN ULONG DestinationLength, - IN ULONG64 Source, - OUT PULONG CopyLength +static FORCEINLINE VOID +__AdapterClearDistribution( + IN PXENNET_ADAPTER Adapter ) { - NDIS_STATUS ndisStatus; + PCHAR Buffer; + PANSI_STRING Distributions; + ULONG Index; + NTSTATUS status; - ndisStatus = __CopyBuffer(Destination, - DestinationLength & ~3, - &Source, - sizeof (ULONG64), - CopyLength); - if (DestinationLength >= 4) - ndisStatus = NDIS_STATUS_SUCCESS; + Trace("====>\n"); - return ndisStatus; -} + status = XENBUS_STORE(Directory, + &Adapter->StoreInterface, + NULL, + NULL, + "drivers", + &Buffer); + if (NT_SUCCESS(status)) { + Distributions = __AdapterMultiSzToUpcaseAnsi(Buffer); -NDIS_STATUS -AdapterQueryInformation( - IN PXENNET_ADAPTER Adapter, - IN PNDIS_OID_REQUEST Request - ) -{ - PVOID Buffer; - ULONG BufferLength; - ULONG BytesNeeded; - ULONG BytesWritten; - ULONG Value32; - ULONGLONG Value64; - ETHERNET_ADDRESS EthernetAddress; - BOOLEAN Warn; - NDIS_STATUS ndisStatus; + XENBUS_STORE(Free, + &Adapter->StoreInterface, + Buffer); + } else { + Distributions = NULL; + } - Buffer = Request->DATA.QUERY_INFORMATION.InformationBuffer; - BufferLength = Request->DATA.QUERY_INFORMATION.InformationBufferLength; - BytesNeeded = BytesWritten = 0; - Warn = TRUE; - ndisStatus = NDIS_STATUS_SUCCESS; + if (Distributions == NULL) + goto done; - switch (Request->DATA.QUERY_INFORMATION.Oid) { - case OID_PNP_CAPABILITIES: - BytesNeeded = sizeof(Adapter->Capabilities); - ndisStatus = __CopyBuffer(Buffer, - BufferLength, - &Adapter->Capabilities, - BytesNeeded, - &BytesWritten); - break; + for (Index = 0; Distributions[Index].Buffer != NULL; Index++) { + PANSI_STRING Distribution = &Distributions[Index]; - case OID_PNP_QUERY_POWER: - BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); - BytesWritten = 0; - // do nothing - break; + status = XENBUS_STORE(Read, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution->Buffer, + &Buffer); + if (!NT_SUCCESS(status)) + continue; - case OID_GEN_SUPPORTED_LIST: - BytesNeeded = sizeof(XennetSupportedOids); - ndisStatus = __CopyBuffer(Buffer, - BufferLength, - &XennetSupportedOids[0], - BytesNeeded, - &BytesWritten); - break; + if (__AdapterMatchDistribution(Adapter, Buffer)) + (VOID) XENBUS_STORE(Remove, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution->Buffer); - case OID_GEN_HARDWARE_STATUS: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - NdisHardwareStatusReady, - &BytesWritten); - break; + XENBUS_STORE(Free, + &Adapter->StoreInterface, + Buffer); + } - case OID_GEN_MEDIA_SUPPORTED: - case OID_GEN_MEDIA_IN_USE: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - XENNET_MEDIA_TYPE, - &BytesWritten); - break; + __AdapterFreeAnsi(Distributions); - case OID_GEN_MAXIMUM_LOOKAHEAD: - case OID_GEN_TRANSMIT_BLOCK_SIZE: - case OID_GEN_RECEIVE_BLOCK_SIZE: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Adapter->MaximumFrameSize, - &BytesWritten); - break; +done: + Trace("<====\n"); +} - case OID_GEN_TRANSMIT_BUFFER_SPACE: - case OID_GEN_RECEIVE_BUFFER_SPACE: - XENVIF_VIF(TransmitterQueryRingSize, - &Adapter->VifInterface, - (PULONG)&Value32); - Value32 *= Adapter->MaximumFrameSize; - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Value32, - &BytesWritten); - break; +#define MAXIMUM_INDEX 255 - case OID_GEN_VENDOR_DESCRIPTION: - BytesNeeded = (ULONG)strlen(VENDOR_NAME_STR) + 1; - ndisStatus = __CopyBuffer(Buffer, - BufferLength, - VENDOR_NAME_STR, - BytesNeeded, - &BytesWritten); - break; +static FORCEINLINE NTSTATUS +__AdapterSetDistribution( + IN PXENNET_ADAPTER Adapter + ) +{ + ULONG Index; + CHAR Distribution[MAXNAMELEN]; + CHAR Vendor[MAXNAMELEN]; + const CHAR *Product; + NTSTATUS status; - case OID_GEN_VENDOR_DRIVER_VERSION: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8, - &BytesWritten); - break; + Trace("====>\n"); - case OID_GEN_DRIVER_VERSION: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (6 << 8) | 0, // NDIS 6.0 - &BytesWritten); - break; + Index = 0; + while (Index <= MAXIMUM_INDEX) { + PCHAR Buffer; - case OID_GEN_MAC_OPTIONS: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - XENNET_MAC_OPTIONS, - &BytesWritten); - break; + status = RtlStringCbPrintfA(Distribution, + MAXNAMELEN, + "%u", + Index); + ASSERT(NT_SUCCESS(status)); - case OID_GEN_STATISTICS: - BytesNeeded = sizeof(NDIS_STATISTICS_INFO); - ndisStatus = AdapterQueryGeneralStatistics(Adapter, - (PNDIS_STATISTICS_INFO)Buffer, - BufferLength, - &BytesWritten); - break; + status = XENBUS_STORE(Read, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution, + &Buffer); + if (!NT_SUCCESS(status)) { + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + goto update; - case OID_802_3_MULTICAST_LIST: - ndisStatus = AdapterQueryMulticastList(Adapter, - Buffer, - BufferLength, - &BytesNeeded, - &BytesWritten); - break; + goto fail1; + } - case OID_802_3_PERMANENT_ADDRESS: - XENVIF_VIF(MacQueryPermanentAddress, - &Adapter->VifInterface, - &EthernetAddress); - BytesNeeded = sizeof(ETHERNET_ADDRESS); - ndisStatus = __CopyBuffer(Buffer, - BufferLength, - &EthernetAddress, - BytesNeeded, - &BytesWritten); - break; + XENBUS_STORE(Free, + &Adapter->StoreInterface, + Buffer); - case OID_802_3_CURRENT_ADDRESS: - XENVIF_VIF(MacQueryCurrentAddress, - &Adapter->VifInterface, - &EthernetAddress); - BytesNeeded = sizeof(ETHERNET_ADDRESS); - ndisStatus = __CopyBuffer(Buffer, - BufferLength, - &EthernetAddress, - BytesNeeded, - &BytesWritten); - break; + Index++; + } - case OID_GEN_MAXIMUM_FRAME_SIZE: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Adapter->MaximumFrameSize - - sizeof(ETHERNET_TAGGED_HEADER), - &BytesWritten); - break; + status = STATUS_UNSUCCESSFUL; + goto fail2; - case OID_GEN_MAXIMUM_TOTAL_SIZE: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Adapter->MaximumFrameSize - - sizeof(ETHERNET_TAGGED_HEADER) + - sizeof (ETHERNET_UNTAGGED_HEADER), - &BytesWritten); - break; +update: + status = RtlStringCbPrintfA(Vendor, + MAXNAMELEN, + "%s", + VENDOR_NAME_STR); + ASSERT(NT_SUCCESS(status)); - case OID_GEN_CURRENT_LOOKAHEAD: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Adapter->CurrentLookahead, - &BytesWritten); - break; + for (Index = 0; Vendor[Index] != '\0'; Index++) + if (!isalnum((UCHAR)Vendor[Index])) + Vendor[Index] = '_'; - case OID_GEN_VENDOR_ID: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - 0x5853, - &BytesWritten); - break; + Product = "XENNET"; - case OID_GEN_LINK_SPEED: - XENVIF_VIF(MacQueryState, - &Adapter->VifInterface, - NULL, - &Value64, - NULL); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)(Value64 / 100), - &BytesWritten); - break; +#if DBG +#define ATTRIBUTES "(DEBUG)" +#else +#define ATTRIBUTES "" +#endif - case OID_GEN_MEDIA_CONNECT_STATUS: - XENVIF_VIF(MacQueryState, - &Adapter->VifInterface, - (PNET_IF_MEDIA_CONNECT_STATE)&Value32, - NULL, - NULL); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Value32, - &BytesWritten); - break; + (VOID) XENBUS_STORE(Printf, + &Adapter->StoreInterface, + NULL, + "drivers", + Distribution, + "%s %s %u.%u.%u %s", + Vendor, + Product, + MAJOR_VERSION, + MINOR_VERSION, + MICRO_VERSION, + ATTRIBUTES + ); - case OID_GEN_MAXIMUM_SEND_PACKETS: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - 16, - &BytesWritten); - break; +#undef ATTRIBUTES - case OID_GEN_CURRENT_PACKET_FILTER: - AdapterGetPacketFilter(Adapter, &Value32); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Value32, - &BytesWritten); - break; + Trace("<====\n"); + return STATUS_SUCCESS; - case OID_GEN_XMIT_OK: - AdapterGetXmitOk(Adapter, &Value64); - BytesNeeded = sizeof(ULONG64); - ndisStatus = __SetUlong64(Buffer, - BufferLength, - Value64, - &BytesWritten); - break; +fail2: + Error("fail2\n"); - case OID_GEN_RCV_OK: - AdapterGetRcvOk(Adapter, &Value64); - BytesNeeded = sizeof(ULONG64); - ndisStatus = __SetUlong64(Buffer, - BufferLength, - Value64, - &BytesWritten); - break; +fail1: + Error("fail1 (%08x)\n", status); - case OID_GEN_XMIT_ERROR: - AdapterGetXmitError(Adapter, &Value32); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Value32, - &BytesWritten); - break; + return status; +} - case OID_GEN_RCV_ERROR: - AdapterGetRcvError(Adapter, &Value32); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - Value32, - &BytesWritten); - break; +static DECLSPEC_NOINLINE VOID +AdapterSuspendCallbackLate( + IN PVOID Argument + ) +{ + PXENNET_ADAPTER Adapter = Argument; - case OID_GEN_RCV_NO_BUFFER: - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - case OID_GEN_RCV_CRC_ERROR: - case OID_802_3_RCV_ERROR_ALIGNMENT: - case OID_802_3_XMIT_ONE_COLLISION: - case OID_802_3_XMIT_MORE_COLLISIONS: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - 0, - &BytesWritten); - break; + (VOID) __AdapterSetDistribution(Adapter); +} - case OID_802_3_MAXIMUM_LIST_SIZE: - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - 32, - &BytesWritten); - break; +static NTSTATUS +AdapterSetDistribution( + IN PXENNET_ADAPTER Adapter + ) +{ + LONG Count; + NTSTATUS status; - case OID_GEN_DIRECTED_BYTES_XMIT: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_TRANSMITTER_UNICAST_OCTETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + Trace("====>\n"); - case OID_GEN_DIRECTED_FRAMES_XMIT: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_TRANSMITTER_UNICAST_PACKETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + Count = InterlockedIncrement(&AdapterCount); + ASSERT(Count != 0); - case OID_GEN_MULTICAST_BYTES_XMIT: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_TRANSMITTER_MULTICAST_OCTETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + if (Count != 1) + goto done; - case OID_GEN_MULTICAST_FRAMES_XMIT: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_TRANSMITTER_MULTICAST_PACKETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + 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 +AdapterEnable( + IN PXENNET_ADAPTER Adapter + ) +{ + NTSTATUS status; + NDIS_STATUS ndisStatus; + + ASSERT(!Adapter->Enabled); + + status = XENBUS_CACHE(Acquire, + &Adapter->CacheInterface); + if (!NT_SUCCESS(status)) + goto fail1; + + status = XENBUS_STORE(Acquire, + &Adapter->StoreInterface); + if (!NT_SUCCESS(status)) + goto fail2; + + status = XENBUS_SUSPEND(Acquire, + &Adapter->SuspendInterface); + if (!NT_SUCCESS(status)) + goto fail3; + + (VOID) AdapterSetDistribution(Adapter); + + ndisStatus = TransmitterEnable(Adapter->Transmitter); + if (ndisStatus != NDIS_STATUS_SUCCESS) + goto fail4; + + ndisStatus = ReceiverEnable(Adapter->Receiver); + if (ndisStatus != NDIS_STATUS_SUCCESS) + goto fail5; + + status = XENVIF_VIF(Enable, + &Adapter->VifInterface, + AdapterVifCallback, + Adapter); + if (!NT_SUCCESS(status)) + goto fail6; + + AdapterMediaStateChange(Adapter); + + Adapter->Enabled = TRUE; + + return NDIS_STATUS_SUCCESS; + +fail6: + ReceiverDisable(Adapter->Receiver); + +fail5: + TransmitterDisable(Adapter->Transmitter); + +fail4: + AdapterClearDistribution(Adapter); + + XENBUS_SUSPEND(Release, &Adapter->SuspendInterface); + +fail3: + XENBUS_STORE(Release, &Adapter->StoreInterface); + +fail2: + XENBUS_CACHE(Release, &Adapter->CacheInterface); + +fail1: + return NDIS_STATUS_FAILURE; +} - case OID_GEN_BROADCAST_BYTES_XMIT: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_TRANSMITTER_BROADCAST_OCTETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; +VOID +AdapterDisable( + IN PXENNET_ADAPTER Adapter + ) +{ + ASSERT(Adapter->Enabled); + Adapter->Enabled = FALSE; - case OID_GEN_BROADCAST_FRAMES_XMIT: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_TRANSMITTER_BROADCAST_PACKETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + XENVIF_VIF(Disable, + &Adapter->VifInterface); - case OID_GEN_DIRECTED_BYTES_RCV: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_RECEIVER_UNICAST_OCTETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + AdapterMediaStateChange(Adapter); - case OID_GEN_DIRECTED_FRAMES_RCV: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_RECEIVER_UNICAST_PACKETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + ReceiverDisable(Adapter->Receiver); + TransmitterDisable(Adapter->Transmitter); - case OID_GEN_MULTICAST_BYTES_RCV: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_RECEIVER_MULTICAST_OCTETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + AdapterClearDistribution(Adapter); - case OID_GEN_MULTICAST_FRAMES_RCV: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_RECEIVER_MULTICAST_PACKETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + XENBUS_SUSPEND(Release, &Adapter->SuspendInterface); + XENBUS_STORE(Release, &Adapter->StoreInterface); + XENBUS_CACHE(Release, &Adapter->CacheInterface); +} - case OID_GEN_BROADCAST_BYTES_RCV: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_RECEIVER_BROADCAST_OCTETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; +VOID +AdapterMediaStateChange( + IN PXENNET_ADAPTER Adapter + ) +{ + NDIS_LINK_STATE LinkState; + NDIS_STATUS_INDICATION StatusIndication; - case OID_GEN_BROADCAST_FRAMES_RCV: - XENVIF_VIF(QueryStatistic, - &Adapter->VifInterface, - XENVIF_RECEIVER_BROADCAST_PACKETS, - &Value64); - BytesNeeded = sizeof(ULONG); - ndisStatus = __SetUlong(Buffer, - BufferLength, - (ULONG)Value64, - &BytesWritten); - break; + RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE)); + LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1; + LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + LinkState.Header.Size = sizeof(NDIS_LINK_STATE); - case OID_GEN_INTERRUPT_MODERATION: - BytesNeeded = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS); - ndisStatus = AdapterInterruptModeration(Adapter, - (PNDIS_INTERRUPT_MODERATION_PARAMETERS)Buffer, - BufferLength, - &BytesWritten); - break; + XENVIF_VIF(MacQueryState, + &Adapter->VifInterface, + &LinkState.MediaConnectState, + &LinkState.RcvLinkSpeed, + &LinkState.MediaDuplexState); - case OID_IP4_OFFLOAD_STATS: - case OID_IP6_OFFLOAD_STATS: - case OID_GEN_SUPPORTED_GUIDS: - // We don't handle these since NDIS 6.0 is supposed to do this for us - case OID_GEN_MAC_ADDRESS: - case OID_GEN_MAX_LINK_SPEED: - // ignore these common unwanted OIDs - case OID_GEN_INIT_TIME_MS: - case OID_GEN_RESET_COUNTS: - case OID_GEN_MEDIA_SENSE_COUNTS: - Warn = FALSE; - /*FALLTHRU*/ - default: - if (Warn) - Warning("UNSUPPORTED OID %08x\n", Request->DATA.QUERY_INFORMATION.Oid); + if (LinkState.MediaConnectState == MediaConnectStateUnknown) { + Info("LINK: STATE UNKNOWN\n"); + } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) { + Info("LINK: DOWN\n"); + } else { + ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected); - ndisStatus = NDIS_STATUS_NOT_SUPPORTED; - break; + if (LinkState.MediaDuplexState == MediaDuplexStateHalf) + Info("LINK: UP: SPEED=%u DUPLEX=HALF\n", LinkState.RcvLinkSpeed); + else if (LinkState.MediaDuplexState == MediaDuplexStateFull) + Info("LINK: UP: SPEED=%u DUPLEX=FULL\n", LinkState.RcvLinkSpeed); + else + Info("LINK: UP: SPEED=%u DUPLEX=UNKNOWN\n", LinkState.RcvLinkSpeed); } - Request->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten; - Request->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded; + LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed; - return ndisStatus; + RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION)); + StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; + StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; + StatusIndication.Header.Size = sizeof (NDIS_STATUS_INDICATION); + + StatusIndication.SourceHandle = Adapter->NdisAdapterHandle; + StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE; + StatusIndication.StatusBuffer = &LinkState; + StatusIndication.StatusBufferSize = sizeof (NDIS_LINK_STATE); + + NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication); } -static NTSTATUS -__QueryInterface( - IN PDEVICE_OBJECT DeviceObject, - IN const GUID *Guid, - IN ULONG Version, - OUT PINTERFACE Interface, - IN ULONG Size, - IN BOOLEAN Optional +NDIS_STATUS +AdapterSetInformation( + IN PXENNET_ADAPTER Adapter, + IN PNDIS_OID_REQUEST Request ) { - KEVENT Event; - IO_STATUS_BLOCK StatusBlock; - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - NTSTATUS status; + PVOID Buffer; + ULONG BufferLength; + ULONG BytesNeeded; + ULONG BytesRead; + BOOLEAN Warn; + NDIS_STATUS ndisStatus; - ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + Buffer = Request->DATA.SET_INFORMATION.InformationBuffer; + BufferLength = Request->DATA.SET_INFORMATION.InformationBufferLength; + BytesNeeded = BytesRead = 0; + Warn = TRUE; + ndisStatus = NDIS_STATUS_SUCCESS; - KeInitializeEvent(&Event, NotificationEvent, FALSE); - RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK)); + switch (Request->DATA.SET_INFORMATION.Oid) { + case OID_PNP_SET_POWER: + BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); + if (BufferLength >= BytesNeeded) { + PNDIS_DEVICE_POWER_STATE PowerState; - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, - DeviceObject, - NULL, - 0, - NULL, - &Event, - &StatusBlock); + PowerState = (PNDIS_DEVICE_POWER_STATE)Buffer; + switch (*PowerState) { + case NdisDeviceStateD0: + Info("SET_POWER: D0\n"); + break; - status = STATUS_UNSUCCESSFUL; - if (Irp == NULL) - goto fail1; + case NdisDeviceStateD1: + Info("SET_POWER: D1\n"); + break; - StackLocation = IoGetNextIrpStackLocation(Irp); - StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; + case NdisDeviceStateD2: + Info("SET_POWER: D2\n"); + break; - StackLocation->Parameters.QueryInterface.InterfaceType = Guid; - StackLocation->Parameters.QueryInterface.Size = (USHORT)Size; - StackLocation->Parameters.QueryInterface.Version = (USHORT)Version; - StackLocation->Parameters.QueryInterface.Interface = Interface; + case NdisDeviceStateD3: + Info("SET_POWER: D3\n"); + break; + } + } + // do nothing + break; - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + case OID_GEN_CURRENT_LOOKAHEAD: + BytesNeeded = sizeof(ULONG); + Adapter->CurrentLookahead = Adapter->MaximumFrameSize; + if (BufferLength == BytesNeeded) { + Adapter->CurrentLookahead = *(PULONG)Buffer; + BytesRead = sizeof(ULONG); + } + break; - status = IoCallDriver(DeviceObject, Irp); - if (status == STATUS_PENDING) { - (VOID) KeWaitForSingleObject(&Event, - Executive, - KernelMode, - FALSE, - NULL); - status = StatusBlock.Status; - } + case OID_GEN_CURRENT_PACKET_FILTER: + BytesNeeded = sizeof(ULONG); + if (BufferLength == BytesNeeded) { + ndisStatus = AdapterSetPacketFilter(Adapter, + (PULONG)Buffer); + BytesRead = sizeof(ULONG); + } + break; - if (!NT_SUCCESS(status)) { - if (status == STATUS_NOT_SUPPORTED && Optional) - goto done; + case OID_802_3_MULTICAST_LIST: + BytesNeeded = ETHERNET_ADDRESS_LENGTH; + if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) { + ndisStatus = AdapterSetMulticastAddresses(Adapter, + Buffer, + BufferLength / ETHERNET_ADDRESS_LENGTH); + if (ndisStatus == NDIS_STATUS_SUCCESS) + BytesRead = BufferLength; + } else { + ndisStatus = NDIS_STATUS_INVALID_LENGTH; + } + break; - goto fail2; - } + case OID_OFFLOAD_ENCAPSULATION: + BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION); + if (BufferLength >= BytesNeeded) { + ndisStatus = AdapterGetOffloadEncapsulation(Adapter, + (PNDIS_OFFLOAD_ENCAPSULATION)Buffer); + if (ndisStatus == NDIS_STATUS_SUCCESS) + BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION); + } + break; -done: - return STATUS_SUCCESS; + case OID_TCP_OFFLOAD_PARAMETERS: + BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS); + if (BufferLength >= BytesNeeded) { + ndisStatus = AdapterGetTcpOffloadParameters(Adapter, + (PNDIS_OFFLOAD_PARAMETERS)Buffer); + if (ndisStatus == NDIS_STATUS_SUCCESS) + BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS); + } + break; -fail2: - Error("fail2\n"); + case OID_GEN_HD_SPLIT_PARAMETERS: + BytesNeeded = sizeof(NDIS_HD_SPLIT_PARAMETERS); + if (BufferLength >= BytesNeeded) { + ndisStatus = AdapterGetHeaderDataSplitParameters(Adapter, + (PNDIS_HD_SPLIT_PARAMETERS)Buffer); + if (ndisStatus == NDIS_STATUS_SUCCESS) + BytesRead = sizeof(NDIS_HD_SPLIT_PARAMETERS); + } + break; -fail1: - Error("fail1 (%08x)\n", status); + case OID_GEN_INTERRUPT_MODERATION: + case OID_GEN_MACHINE_NAME: + Warn = FALSE; + /*FALLTHRU*/ + default: + if (Warn) + Warning("UNSUPPORTED OID %08x\n", Request->DATA.QUERY_INFORMATION.Oid); - return status; -} + ndisStatus = NDIS_STATUS_NOT_SUPPORTED; + break; + } -#pragma prefast(push) -#pragma prefast(disable:6102) + Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded; + if (ndisStatus == NDIS_STATUS_SUCCESS) + Request->DATA.SET_INFORMATION.BytesRead = BytesRead; -#define READ_PROPERTY(field, name, defaultval, handle) \ - do { \ - NDIS_STATUS _Status; \ - NDIS_STRING _Value; \ - PNDIS_CONFIGURATION_PARAMETER _Data; \ - RtlInitUnicodeString(&_Value, name); \ - NdisReadConfiguration(&_Status, &_Data, handle, \ - &_Value, NdisParameterInteger); \ - if (_Status == NDIS_STATUS_SUCCESS) \ - field = _Data->ParameterData.IntegerData; \ - else \ - field = defaultval; \ - } while (FALSE); + return ndisStatus; +} -static NDIS_STATUS -AdapterGetAdvancedSettings( - IN PXENNET_ADAPTER Adapter +static FORCEINLINE NDIS_STATUS +__CopyBuffer( + IN PVOID Destination, + IN ULONG DestinationLength, + IN PVOID Source, + IN ULONG SourceLength, + OUT PULONG CopyLength ) { - NDIS_CONFIGURATION_OBJECT Config; - NDIS_HANDLE Handle; - NDIS_STATUS ndisStatus; - - RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT)); - Config.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT; - Config.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1; - Config.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT); - Config.NdisHandle = Adapter->NdisAdapterHandle; - Config.Flags = 0; - - ndisStatus = NdisOpenConfigurationEx(&Config, &Handle); - if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail1; - - READ_PROPERTY(Adapter->Properties.ipv4_csum, L"*IPChecksumOffloadIPv4", 3, Handle); - READ_PROPERTY(Adapter->Properties.tcpv4_csum, L"*TCPChecksumOffloadIPv4", 3, Handle); - READ_PROPERTY(Adapter->Properties.udpv4_csum, L"*UDPChecksumOffloadIPv4", 3, Handle); - READ_PROPERTY(Adapter->Properties.tcpv6_csum, L"*TCPChecksumOffloadIPv6", 3, Handle); - READ_PROPERTY(Adapter->Properties.udpv6_csum, L"*UDPChecksumOffloadIPv6", 3, Handle); - READ_PROPERTY(Adapter->Properties.lsov4, L"*LSOv2IPv4", 1, Handle); - READ_PROPERTY(Adapter->Properties.lsov6, L"*LSOv2IPv6", 1, Handle); - READ_PROPERTY(Adapter->Properties.lrov4, L"LROIPv4", 1, Handle); - READ_PROPERTY(Adapter->Properties.lrov6, L"LROIPv6", 1, Handle); - READ_PROPERTY(Adapter->Properties.need_csum_value, L"NeedChecksumValue", 1, Handle); - READ_PROPERTY(Adapter->Properties.HeaderDataSplit, L"*HeaderDataSplit", 1, Handle); - - NdisCloseConfiguration(Handle); - - return NDIS_STATUS_SUCCESS; + *CopyLength = __min(SourceLength, DestinationLength); + RtlCopyMemory(Destination, Source, *CopyLength); -fail1: - return NDIS_STATUS_FAILURE; + return (DestinationLength >= SourceLength) ? + NDIS_STATUS_SUCCESS : + NDIS_STATUS_BUFFER_TOO_SHORT; } -#undef READ_PROPERTY - -#pragma prefast(pop) - -static NDIS_STATUS -AdapterSetRegistrationAttributes( - IN PXENNET_ADAPTER Adapter +static FORCEINLINE NDIS_STATUS +__SetUlong( + IN PVOID Destination, + IN ULONG DestinationLength, + IN ULONG Source, + OUT PULONG CopyLength ) { - NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES Attribs; - NDIS_STATUS ndisStatus; + return __CopyBuffer(Destination, + DestinationLength & ~3, + &Source, + sizeof (ULONG), + CopyLength); +} - RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES)); - Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; - Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; - Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES); - Attribs.MiniportAdapterContext = (NDIS_HANDLE)Adapter; - Attribs.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER | - NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND; - Attribs.CheckForHangTimeInSeconds = 0; - Attribs.InterfaceType = XENNET_INTERFACE_TYPE; +static FORCEINLINE NDIS_STATUS +__SetUlong64( + IN PVOID Destination, + IN ULONG DestinationLength, + IN ULONG64 Source, + OUT PULONG CopyLength + ) +{ + NDIS_STATUS ndisStatus; - ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); + ndisStatus = __CopyBuffer(Destination, + DestinationLength & ~3, + &Source, + sizeof (ULONG64), + CopyLength); + if (DestinationLength >= 4) + ndisStatus = NDIS_STATUS_SUCCESS; return ndisStatus; } -static NDIS_STATUS -AdapterSetGeneralAttributes( - IN PXENNET_ADAPTER Adapter +NDIS_STATUS +AdapterQueryInformation( + IN PXENNET_ADAPTER Adapter, + IN PNDIS_OID_REQUEST Request ) { - NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES Attribs; - NDIS_STATUS ndisStatus; - - RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES)); - Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; - Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; - Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); - Attribs.MediaType = XENNET_MEDIA_TYPE; - - XENVIF_VIF(MacQueryMaximumFrameSize, - &Adapter->VifInterface, - (PULONG)&Adapter->MaximumFrameSize); - - Attribs.MtuSize = Adapter->MaximumFrameSize - sizeof (ETHERNET_TAGGED_HEADER); - Attribs.MaxXmitLinkSpeed = XENNET_MEDIA_MAX_SPEED; - Attribs.MaxRcvLinkSpeed = XENNET_MEDIA_MAX_SPEED; - Attribs.XmitLinkSpeed = XENNET_MEDIA_MAX_SPEED; - Attribs.RcvLinkSpeed = XENNET_MEDIA_MAX_SPEED; - Attribs.MediaConnectState = MediaConnectStateConnected; - Attribs.MediaDuplexState = MediaDuplexStateFull; - Attribs.LookaheadSize = Adapter->MaximumFrameSize; - Attribs.PowerManagementCapabilities = &Adapter->Capabilities; - Attribs.MacOptions = XENNET_MAC_OPTIONS; - Attribs.SupportedPacketFilters = XENNET_SUPPORTED_PACKET_FILTERS; - Attribs.MaxMulticastListSize = 32; - Attribs.MacAddressLength = ETHERNET_ADDRESS_LENGTH; - - XENVIF_VIF(MacQueryPermanentAddress, - &Adapter->VifInterface, - (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress); - XENVIF_VIF(MacQueryCurrentAddress, - &Adapter->VifInterface, - (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress); + PVOID Buffer; + ULONG BufferLength; + ULONG BytesNeeded; + ULONG BytesWritten; + ULONG Value32; + ULONGLONG Value64; + ETHERNET_ADDRESS EthernetAddress; + BOOLEAN Warn; + NDIS_STATUS ndisStatus; - Attribs.PhysicalMediumType = NdisPhysicalMedium802_3; - Attribs.RecvScaleCapabilities = NULL; - Attribs.AccessType = NET_IF_ACCESS_BROADCAST; - Attribs.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; - Attribs.ConnectionType = NET_IF_CONNECTION_DEDICATED; - Attribs.IfType = IF_TYPE_ETHERNET_CSMACD; - Attribs.IfConnectorPresent = TRUE; - Attribs.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | - NDIS_STATISTICS_XMIT_ERROR_SUPPORTED | - NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED | - NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED | - NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED | - NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED | - NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED | - NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED | - NDIS_STATISTICS_RCV_OK_SUPPORTED | - NDIS_STATISTICS_RCV_ERROR_SUPPORTED | - NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED | - NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED | - NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED | - NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED | - NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED | - NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED | - NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; - - Attribs.SupportedOidList = XennetSupportedOids; - Attribs.SupportedOidListLength = sizeof(XennetSupportedOids); + Buffer = Request->DATA.QUERY_INFORMATION.InformationBuffer; + BufferLength = Request->DATA.QUERY_INFORMATION.InformationBufferLength; + BytesNeeded = BytesWritten = 0; + Warn = TRUE; + ndisStatus = NDIS_STATUS_SUCCESS; - ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); + switch (Request->DATA.QUERY_INFORMATION.Oid) { + case OID_PNP_CAPABILITIES: + BytesNeeded = sizeof(Adapter->Capabilities); + ndisStatus = __CopyBuffer(Buffer, + BufferLength, + &Adapter->Capabilities, + BytesNeeded, + &BytesWritten); + break; - return ndisStatus; -} + case OID_PNP_QUERY_POWER: + BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); -static NDIS_STATUS -AdapterSetOffloadAttributes( - IN PXENNET_ADAPTER Adapter - ) -{ - NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES Attribs; - XENVIF_VIF_OFFLOAD_OPTIONS Options; - PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions; - PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions; - NDIS_OFFLOAD Default; - NDIS_OFFLOAD Supported; - NDIS_STATUS ndisStatus; + if (BufferLength >= BytesNeeded) { + PNDIS_DEVICE_POWER_STATE PowerState; - TxOptions = TransmitterOffloadOptions(Adapter->Transmitter); - RxOptions = ReceiverOffloadOptions(Adapter->Receiver); + PowerState = (PNDIS_DEVICE_POWER_STATE)Buffer; + switch (*PowerState) { + case NdisDeviceStateD0: + Info("QUERY_POWER: D0\n"); + break; - TxOptions->Value = 0; - TxOptions->OffloadTagManipulation = 1; + case NdisDeviceStateD1: + Info("QUERY_POWER: D1\n"); + break; - RxOptions->Value = 0; - RxOptions->OffloadTagManipulation = 1; + case NdisDeviceStateD2: + Info("QUERY_POWER: D2\n"); + break; - if (Adapter->Properties.need_csum_value) - RxOptions->NeedChecksumValue = 1; + case NdisDeviceStateD3: + Info("QUERY_POWER: D3\n"); + break; + } + } - if (Adapter->Properties.lrov4) { - RxOptions->OffloadIpVersion4LargePacket = 1; - RxOptions->NeedLargePacketSplit = 1; - } + BytesWritten = 0; + // do nothing + break; - if (Adapter->Properties.lrov6) { - RxOptions->OffloadIpVersion6LargePacket = 1; - RxOptions->NeedLargePacketSplit = 1; - } + case OID_GEN_SUPPORTED_LIST: + BytesNeeded = sizeof(XennetSupportedOids); + ndisStatus = __CopyBuffer(Buffer, + BufferLength, + &XennetSupportedOids[0], + BytesNeeded, + &BytesWritten); + break; - XENVIF_VIF(ReceiverSetOffloadOptions, - &Adapter->VifInterface, - *RxOptions); + case OID_GEN_HARDWARE_STATUS: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + NdisHardwareStatusReady, + &BytesWritten); + break; - XENVIF_VIF(TransmitterQueryOffloadOptions, - &Adapter->VifInterface, - &Options); + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + XENNET_MEDIA_TYPE, + &BytesWritten); + break; - RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD)); - Supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; - Supported.Header.Revision = NDIS_OFFLOAD_REVISION_1; - Supported.Header.Size = sizeof(NDIS_OFFLOAD); + case OID_GEN_MAXIMUM_LOOKAHEAD: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Adapter->MaximumFrameSize, + &BytesWritten); + break; - Supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; + case OID_GEN_TRANSMIT_BUFFER_SPACE: + case OID_GEN_RECEIVE_BUFFER_SPACE: + XENVIF_VIF(TransmitterQueryRingSize, + &Adapter->VifInterface, + (PULONG)&Value32); + Value32 *= Adapter->MaximumFrameSize; + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Value32, + &BytesWritten); + break; - Supported.Checksum.IPv4Receive.IpChecksum = 1; - Supported.Checksum.IPv4Receive.IpOptionsSupported = 1; + case OID_GEN_VENDOR_DESCRIPTION: + BytesNeeded = (ULONG)strlen(VENDOR_NAME_STR) + 1; + ndisStatus = __CopyBuffer(Buffer, + BufferLength, + VENDOR_NAME_STR, + BytesNeeded, + &BytesWritten); + break; - Supported.Checksum.IPv4Receive.TcpChecksum = 1; - Supported.Checksum.IPv4Receive.TcpOptionsSupported = 1; + case OID_GEN_VENDOR_DRIVER_VERSION: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8, + &BytesWritten); + break; - Supported.Checksum.IPv4Receive.UdpChecksum = 1; + case OID_GEN_DRIVER_VERSION: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (6 << 8) | 0, // NDIS 6.0 + &BytesWritten); + break; - Supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; + case OID_GEN_MAC_OPTIONS: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + XENNET_MAC_OPTIONS, + &BytesWritten); + break; - Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1; + case OID_GEN_STATISTICS: + BytesNeeded = sizeof(NDIS_STATISTICS_INFO); + ndisStatus = AdapterQueryGeneralStatistics(Adapter, + (PNDIS_STATISTICS_INFO)Buffer, + BufferLength, + &BytesWritten); + break; - Supported.Checksum.IPv6Receive.TcpChecksum = 1; - Supported.Checksum.IPv6Receive.TcpOptionsSupported = 1; + case OID_802_3_MULTICAST_LIST: + ndisStatus = AdapterQueryMulticastList(Adapter, + Buffer, + BufferLength, + &BytesNeeded, + &BytesWritten); + break; - Supported.Checksum.IPv6Receive.UdpChecksum = 1; + case OID_802_3_PERMANENT_ADDRESS: + XENVIF_VIF(MacQueryPermanentAddress, + &Adapter->VifInterface, + &EthernetAddress); + BytesNeeded = sizeof(ETHERNET_ADDRESS); + ndisStatus = __CopyBuffer(Buffer, + BufferLength, + &EthernetAddress, + BytesNeeded, + &BytesWritten); + break; - Supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; + case OID_802_3_CURRENT_ADDRESS: + XENVIF_VIF(MacQueryCurrentAddress, + &Adapter->VifInterface, + &EthernetAddress); + BytesNeeded = sizeof(ETHERNET_ADDRESS); + ndisStatus = __CopyBuffer(Buffer, + BufferLength, + &EthernetAddress, + BytesNeeded, + &BytesWritten); + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Adapter->MaximumFrameSize - + sizeof(ETHERNET_TAGGED_HEADER), + &BytesWritten); + break; + + case OID_GEN_MAXIMUM_TOTAL_SIZE: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Adapter->MaximumFrameSize - + sizeof(ETHERNET_TAGGED_HEADER) + + sizeof (ETHERNET_UNTAGGED_HEADER), + &BytesWritten); + break; + + case OID_GEN_CURRENT_LOOKAHEAD: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Adapter->CurrentLookahead, + &BytesWritten); + break; + + case OID_GEN_VENDOR_ID: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + 0x5853, + &BytesWritten); + break; + + case OID_GEN_LINK_SPEED: + XENVIF_VIF(MacQueryState, + &Adapter->VifInterface, + NULL, + &Value64, + NULL); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)(Value64 / 100), + &BytesWritten); + break; + + case OID_GEN_MEDIA_CONNECT_STATUS: + XENVIF_VIF(MacQueryState, + &Adapter->VifInterface, + (PNET_IF_MEDIA_CONNECT_STATE)&Value32, + NULL, + NULL); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Value32, + &BytesWritten); + break; + + case OID_GEN_MAXIMUM_SEND_PACKETS: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + 16, + &BytesWritten); + break; - if (Options.OffloadIpVersion4HeaderChecksum) { - Supported.Checksum.IPv4Transmit.IpChecksum = 1; - Supported.Checksum.IPv4Transmit.IpOptionsSupported = 1; - } + case OID_GEN_CURRENT_PACKET_FILTER: + AdapterGetPacketFilter(Adapter, &Value32); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Value32, + &BytesWritten); + break; - if (Options.OffloadIpVersion4TcpChecksum) { - Supported.Checksum.IPv4Transmit.TcpChecksum = 1; - Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1; - } + case OID_GEN_XMIT_OK: + AdapterGetXmitOk(Adapter, &Value64); + BytesNeeded = sizeof(ULONG64); + ndisStatus = __SetUlong64(Buffer, + BufferLength, + Value64, + &BytesWritten); + break; - if (Options.OffloadIpVersion4UdpChecksum) - Supported.Checksum.IPv4Transmit.UdpChecksum = 1; + case OID_GEN_RCV_OK: + AdapterGetRcvOk(Adapter, &Value64); + BytesNeeded = sizeof(ULONG64); + ndisStatus = __SetUlong64(Buffer, + BufferLength, + Value64, + &BytesWritten); + break; - Supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; + case OID_GEN_XMIT_ERROR: + AdapterGetXmitError(Adapter, &Value32); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Value32, + &BytesWritten); + break; - Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1; + case OID_GEN_RCV_ERROR: + AdapterGetRcvError(Adapter, &Value32); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + Value32, + &BytesWritten); + break; - if (Options.OffloadIpVersion6TcpChecksum) { - Supported.Checksum.IPv6Transmit.TcpChecksum = 1; - Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1; - } + case OID_GEN_RCV_NO_BUFFER: + case OID_GEN_TRANSMIT_QUEUE_LENGTH: + case OID_GEN_RCV_CRC_ERROR: + case OID_802_3_RCV_ERROR_ALIGNMENT: + case OID_802_3_XMIT_ONE_COLLISION: + case OID_802_3_XMIT_MORE_COLLISIONS: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + 0, + &BytesWritten); + break; - if (Options.OffloadIpVersion6UdpChecksum) - Supported.Checksum.IPv6Transmit.UdpChecksum = 1; + case OID_802_3_MAXIMUM_LIST_SIZE: + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + 32, + &BytesWritten); + break; - if (Options.OffloadIpVersion4LargePacket) { - XENVIF_VIF(TransmitterQueryLargePacketSize, + case OID_GEN_DIRECTED_BYTES_XMIT: + XENVIF_VIF(QueryStatistic, &Adapter->VifInterface, - 4, - &Supported.LsoV2.IPv4.MaxOffLoadSize); - Supported.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; - Supported.LsoV2.IPv4.MinSegmentCount = 2; - } + XENVIF_TRANSMITTER_UNICAST_OCTETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (Options.OffloadIpVersion6LargePacket) { - XENVIF_VIF(TransmitterQueryLargePacketSize, + case OID_GEN_DIRECTED_FRAMES_XMIT: + XENVIF_VIF(QueryStatistic, &Adapter->VifInterface, - 6, - &Supported.LsoV2.IPv6.MaxOffLoadSize); - Supported.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; - Supported.LsoV2.IPv6.MinSegmentCount = 2; - Supported.LsoV2.IPv6.IpExtensionHeadersSupported = 1; - Supported.LsoV2.IPv6.TcpOptionsSupported = 1; - } - - Default = Supported; + XENVIF_TRANSMITTER_UNICAST_PACKETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.ipv4_csum & 2)) - Default.Checksum.IPv4Receive.IpChecksum = 0; + case OID_GEN_MULTICAST_BYTES_XMIT: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_TRANSMITTER_MULTICAST_OCTETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.tcpv4_csum & 2)) - Default.Checksum.IPv4Receive.TcpChecksum = 0; + case OID_GEN_MULTICAST_FRAMES_XMIT: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_TRANSMITTER_MULTICAST_PACKETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.udpv4_csum & 2)) - Default.Checksum.IPv4Receive.UdpChecksum = 0; + case OID_GEN_BROADCAST_BYTES_XMIT: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_TRANSMITTER_BROADCAST_OCTETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.tcpv6_csum & 2)) - Default.Checksum.IPv6Receive.TcpChecksum = 0; + case OID_GEN_BROADCAST_FRAMES_XMIT: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_TRANSMITTER_BROADCAST_PACKETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.udpv6_csum & 2)) - Default.Checksum.IPv6Receive.UdpChecksum = 0; + case OID_GEN_DIRECTED_BYTES_RCV: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_RECEIVER_UNICAST_OCTETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.ipv4_csum & 1)) - Default.Checksum.IPv4Transmit.IpChecksum = 0; + case OID_GEN_DIRECTED_FRAMES_RCV: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_RECEIVER_UNICAST_PACKETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.tcpv4_csum & 1)) - Default.Checksum.IPv4Transmit.TcpChecksum = 0; + case OID_GEN_MULTICAST_BYTES_RCV: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_RECEIVER_MULTICAST_OCTETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.udpv4_csum & 1)) - Default.Checksum.IPv4Transmit.UdpChecksum = 0; + case OID_GEN_MULTICAST_FRAMES_RCV: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_RECEIVER_MULTICAST_PACKETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.tcpv6_csum & 1)) - Default.Checksum.IPv6Transmit.TcpChecksum = 0; + case OID_GEN_BROADCAST_BYTES_RCV: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_RECEIVER_BROADCAST_OCTETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.udpv6_csum & 1)) - Default.Checksum.IPv6Transmit.UdpChecksum = 0; + case OID_GEN_BROADCAST_FRAMES_RCV: + XENVIF_VIF(QueryStatistic, + &Adapter->VifInterface, + XENVIF_RECEIVER_BROADCAST_PACKETS, + &Value64); + BytesNeeded = sizeof(ULONG); + ndisStatus = __SetUlong(Buffer, + BufferLength, + (ULONG)Value64, + &BytesWritten); + break; - if (!(Adapter->Properties.lsov4)) { - Default.LsoV2.IPv4.MaxOffLoadSize = 0; - Default.LsoV2.IPv4.MinSegmentCount = 0; - } + case OID_GEN_INTERRUPT_MODERATION: + BytesNeeded = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS); + ndisStatus = AdapterInterruptModeration(Adapter, + (PNDIS_INTERRUPT_MODERATION_PARAMETERS)Buffer, + BufferLength, + &BytesWritten); + break; - if (!(Adapter->Properties.lsov6)) { - Default.LsoV2.IPv6.MaxOffLoadSize = 0; - Default.LsoV2.IPv6.MinSegmentCount = 0; - } + case OID_IP4_OFFLOAD_STATS: + case OID_IP6_OFFLOAD_STATS: + case OID_GEN_SUPPORTED_GUIDS: + // We don't handle these since NDIS 6.0 is supposed to do this for us + case OID_GEN_MAC_ADDRESS: + case OID_GEN_MAX_LINK_SPEED: + // ignore these common unwanted OIDs + case OID_GEN_INIT_TIME_MS: + case OID_GEN_RESET_COUNTS: + case OID_GEN_MEDIA_SENSE_COUNTS: + Warn = FALSE; + /*FALLTHRU*/ + default: + if (Warn) + Warning("UNSUPPORTED OID %08x\n", Request->DATA.QUERY_INFORMATION.Oid); - if (!RtlEqualMemory(&Adapter->Offload, &Default, sizeof (NDIS_OFFLOAD))) { - Adapter->Offload = Default; - DISPLAY_OFFLOAD(Default); + ndisStatus = NDIS_STATUS_NOT_SUPPORTED; + break; } - RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES)); - Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES; - Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1; - Attribs.Header.Size = sizeof(Attribs); - Attribs.DefaultOffloadConfiguration = &Default; - Attribs.HardwareOffloadCapabilities = &Supported; + Request->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten; + Request->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded; - ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); return ndisStatus; } -static NDIS_STATUS -AdapterSetHeaderDataSplitAttributes( - IN PXENNET_ADAPTER Adapter +static NTSTATUS +__QueryInterface( + IN PDEVICE_OBJECT DeviceObject, + IN const GUID *Guid, + IN ULONG Version, + OUT PINTERFACE Interface, + IN ULONG Size, + IN BOOLEAN Optional ) { - NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES Attribs; - NDIS_HD_SPLIT_ATTRIBUTES Split; - NDIS_STATUS NdisStatus; - - RtlZeroMemory(&Attribs, sizeof(Attribs)); + KEVENT Event; + IO_STATUS_BLOCK StatusBlock; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + NTSTATUS status; - Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES; - Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; - Attribs.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - RtlZeroMemory(&Split, sizeof(Split)); + KeInitializeEvent(&Event, NotificationEvent, FALSE); + RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK)); - Split.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES; - Split.Header.Revision = NDIS_HD_SPLIT_ATTRIBUTES_REVISION_1; - Split.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1; - Split.HardwareCapabilities = - NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT | - NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS | - NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS | - NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS; + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, + DeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); - if (Adapter->Properties.HeaderDataSplit != 0) - Split.CurrentCapabilities = Split.HardwareCapabilities; + status = STATUS_UNSUCCESSFUL; + if (Irp == NULL) + goto fail1; - Attribs.HDSplitAttributes = &Split; + StackLocation = IoGetNextIrpStackLocation(Irp); + StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; - NdisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, - (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); - if (NdisStatus != NDIS_STATUS_SUCCESS) - goto fail1; + StackLocation->Parameters.QueryInterface.InterfaceType = Guid; + StackLocation->Parameters.QueryInterface.Size = (USHORT)Size; + StackLocation->Parameters.QueryInterface.Version = (USHORT)Version; + StackLocation->Parameters.QueryInterface.Interface = Interface; - if (Split.HDSplitFlags == NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) { - ASSERT(Split.CurrentCapabilities & NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT); + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - Info("BackfillSize = %u\n", Split.BackfillSize); - Info("MaxHeaderSize = %u\n", Split.MaxHeaderSize); + status = IoCallDriver(DeviceObject, Irp); + if (status == STATUS_PENDING) { + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + status = StatusBlock.Status; + } - XENVIF_VIF(ReceiverSetBackfillSize, - &Adapter->VifInterface, - Split.BackfillSize); + if (!NT_SUCCESS(status)) { + if (status == STATUS_NOT_SUPPORTED && Optional) + goto done; - ReceiverSplitHeaderData(Adapter->Receiver, Split.MaxHeaderSize); + goto fail2; } - return NDIS_STATUS_SUCCESS; +done: + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); fail1: - Error("fail1 (%08x)\n", NdisStatus); + Error("fail1 (%08x)\n", status); - return NdisStatus; + return status; } -static FORCEINLINE PVOID -__AdapterAllocate( - IN ULONG Length - ) -{ - return __AllocateNonPagedPoolWithTag(Length, ADAPTER_POOL_TAG); -} +#pragma prefast(push) +#pragma prefast(disable:6102) -static FORCEINLINE VOID -__AdapterFree( - IN PVOID Buffer - ) -{ - __FreePoolWithTag(Buffer, ADAPTER_POOL_TAG); -} +#define READ_PROPERTY(field, name, defaultval, handle) \ + do { \ + NDIS_STATUS _Status; \ + NDIS_STRING _Value; \ + PNDIS_CONFIGURATION_PARAMETER _Data; \ + RtlInitUnicodeString(&_Value, name); \ + NdisReadConfiguration(&_Status, &_Data, handle, \ + &_Value, NdisParameterInteger); \ + if (_Status == NDIS_STATUS_SUCCESS) \ + field = _Data->ParameterData.IntegerData; \ + else \ + field = defaultval; \ + } while (FALSE); -static FORCEINLINE PANSI_STRING -__AdapterMultiSzToUpcaseAnsi( - IN PCHAR Buffer +static NDIS_STATUS +AdapterGetAdvancedSettings( + IN PXENNET_ADAPTER Adapter ) { - 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++; - } - } + NDIS_CONFIGURATION_OBJECT Config; + NDIS_HANDLE Handle; + NDIS_STATUS ndisStatus; - Ansi = __AdapterAllocate(sizeof (ANSI_STRING) * (Count + 1)); + RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT)); + Config.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT; + Config.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1; + Config.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT); + Config.NdisHandle = Adapter->NdisAdapterHandle; + Config.Flags = 0; - status = STATUS_NO_MEMORY; - if (Ansi == NULL) + ndisStatus = NdisOpenConfigurationEx(&Config, &Handle); + if (ndisStatus != NDIS_STATUS_SUCCESS) 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"); + READ_PROPERTY(Adapter->Properties.ipv4_csum, L"*IPChecksumOffloadIPv4", 3, Handle); + READ_PROPERTY(Adapter->Properties.tcpv4_csum, L"*TCPChecksumOffloadIPv4", 3, Handle); + READ_PROPERTY(Adapter->Properties.udpv4_csum, L"*UDPChecksumOffloadIPv4", 3, Handle); + READ_PROPERTY(Adapter->Properties.tcpv6_csum, L"*TCPChecksumOffloadIPv6", 3, Handle); + READ_PROPERTY(Adapter->Properties.udpv6_csum, L"*UDPChecksumOffloadIPv6", 3, Handle); + READ_PROPERTY(Adapter->Properties.lsov4, L"*LSOv2IPv4", 1, Handle); + READ_PROPERTY(Adapter->Properties.lsov6, L"*LSOv2IPv6", 1, Handle); + READ_PROPERTY(Adapter->Properties.lrov4, L"LROIPv4", 1, Handle); + READ_PROPERTY(Adapter->Properties.lrov6, L"LROIPv6", 1, Handle); + READ_PROPERTY(Adapter->Properties.need_csum_value, L"NeedChecksumValue", 1, Handle); + READ_PROPERTY(Adapter->Properties.HeaderDataSplit, L"*HeaderDataSplit", 1, Handle); - while (--Index >= 0) - __AdapterFree(Ansi[Index].Buffer); + NdisCloseConfiguration(Handle); - __AdapterFree(Ansi); + return NDIS_STATUS_SUCCESS; fail1: - Error("fail1 (%08x)\n", status); - - return NULL; + return NDIS_STATUS_FAILURE; } -static FORCEINLINE VOID -__AdapterFreeAnsi( - IN PANSI_STRING Ansi +#undef READ_PROPERTY + +#pragma prefast(pop) + +static NDIS_STATUS +AdapterSetRegistrationAttributes( + IN PXENNET_ADAPTER Adapter ) { - ULONG Index; + NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES Attribs; + NDIS_STATUS ndisStatus; + + RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES)); + Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES; + Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1; + Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES); + Attribs.MiniportAdapterContext = (NDIS_HANDLE)Adapter; + Attribs.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER | + NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND; + Attribs.CheckForHangTimeInSeconds = 0; + Attribs.InterfaceType = XENNET_INTERFACE_TYPE; - for (Index = 0; Ansi[Index].Buffer != NULL; Index++) - __AdapterFree(Ansi[Index].Buffer); + ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); - __AdapterFree(Ansi); + return ndisStatus; } -static FORCEINLINE BOOLEAN -__AdapterMatchDistribution( - IN PXENNET_ADAPTER Adapter, - IN PCHAR Buffer +static NDIS_STATUS +AdapterSetGeneralAttributes( + IN PXENNET_ADAPTER Adapter ) { - PCHAR Vendor; - PCHAR Product; - PCHAR Context; - const CHAR *Text; - BOOLEAN Match; - ULONG Index; - NTSTATUS status; + NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES Attribs; + NDIS_STATUS ndisStatus; - UNREFERENCED_PARAMETER(Adapter); + RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES)); + Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; + Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; + Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); + Attribs.MediaType = XENNET_MEDIA_TYPE; - status = STATUS_INVALID_PARAMETER; + XENVIF_VIF(MacQueryMaximumFrameSize, + &Adapter->VifInterface, + (PULONG)&Adapter->MaximumFrameSize); - Vendor = __strtok_r(Buffer, " ", &Context); - if (Vendor == NULL) - goto fail1; + Attribs.MtuSize = Adapter->MaximumFrameSize - sizeof (ETHERNET_TAGGED_HEADER); + Attribs.MaxXmitLinkSpeed = XENNET_MEDIA_MAX_SPEED; + Attribs.MaxRcvLinkSpeed = XENNET_MEDIA_MAX_SPEED; + Attribs.XmitLinkSpeed = XENNET_MEDIA_MAX_SPEED; + Attribs.RcvLinkSpeed = XENNET_MEDIA_MAX_SPEED; + Attribs.MediaConnectState = MediaConnectStateConnected; + Attribs.MediaDuplexState = MediaDuplexStateFull; + Attribs.LookaheadSize = Adapter->MaximumFrameSize; + Attribs.PowerManagementCapabilities = &Adapter->Capabilities; + Attribs.MacOptions = XENNET_MAC_OPTIONS; + Attribs.SupportedPacketFilters = XENNET_SUPPORTED_PACKET_FILTERS; + Attribs.MaxMulticastListSize = 32; + Attribs.MacAddressLength = ETHERNET_ADDRESS_LENGTH; - Product = __strtok_r(NULL, " ", &Context); - if (Product == NULL) - goto fail2; + XENVIF_VIF(MacQueryPermanentAddress, + &Adapter->VifInterface, + (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress); + XENVIF_VIF(MacQueryCurrentAddress, + &Adapter->VifInterface, + (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress); - Match = TRUE; + Attribs.PhysicalMediumType = NdisPhysicalMedium802_3; + Attribs.RecvScaleCapabilities = NULL; + Attribs.AccessType = NET_IF_ACCESS_BROADCAST; + Attribs.DirectionType = NET_IF_DIRECTION_SENDRECEIVE; + Attribs.ConnectionType = NET_IF_CONNECTION_DEDICATED; + Attribs.IfType = IF_TYPE_ETHERNET_CSMACD; + Attribs.IfConnectorPresent = TRUE; + Attribs.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | + NDIS_STATISTICS_XMIT_ERROR_SUPPORTED | + NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED | + NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED | + NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED | + NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED | + NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED | + NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED | + NDIS_STATISTICS_RCV_OK_SUPPORTED | + NDIS_STATISTICS_RCV_ERROR_SUPPORTED | + NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED | + NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED | + NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED | + NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED | + NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED | + NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED | + NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; + + Attribs.SupportedOidList = XennetSupportedOids; + Attribs.SupportedOidListLength = sizeof(XennetSupportedOids); - Text = VENDOR_NAME_STR; + ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); - 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; - } - } - } + return ndisStatus; +} - Text = "XENNET"; +static NDIS_STATUS +AdapterSetOffloadAttributes( + IN PXENNET_ADAPTER Adapter + ) +{ + NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES Attribs; + XENVIF_VIF_OFFLOAD_OPTIONS Options; + PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions; + PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions; + NDIS_OFFLOAD Default; + NDIS_OFFLOAD Supported; + NDIS_STATUS ndisStatus; - if (_stricmp(Product, Text) != 0) - Match = FALSE; + TxOptions = TransmitterOffloadOptions(Adapter->Transmitter); + RxOptions = ReceiverOffloadOptions(Adapter->Receiver); - return Match; + TxOptions->Value = 0; + TxOptions->OffloadTagManipulation = 1; -fail2: - Error("fail2\n"); + RxOptions->Value = 0; + RxOptions->OffloadTagManipulation = 1; -fail1: - Error("fail1 (%08x)\n", status); + if (Adapter->Properties.need_csum_value) + RxOptions->NeedChecksumValue = 1; - return FALSE; -} + if (Adapter->Properties.lrov4) { + RxOptions->OffloadIpVersion4LargePacket = 1; + RxOptions->NeedLargePacketSplit = 1; + } -static FORCEINLINE VOID -__AdapterClearDistribution( - IN PXENNET_ADAPTER Adapter - ) -{ - PCHAR Buffer; - PANSI_STRING Distributions; - ULONG Index; - NTSTATUS status; + if (Adapter->Properties.lrov6) { + RxOptions->OffloadIpVersion6LargePacket = 1; + RxOptions->NeedLargePacketSplit = 1; + } - Trace("====>\n"); + XENVIF_VIF(ReceiverSetOffloadOptions, + &Adapter->VifInterface, + *RxOptions); - status = XENBUS_STORE(Directory, - &Adapter->StoreInterface, - NULL, - NULL, - "drivers", - &Buffer); - if (NT_SUCCESS(status)) { - Distributions = __AdapterMultiSzToUpcaseAnsi(Buffer); + XENVIF_VIF(TransmitterQueryOffloadOptions, + &Adapter->VifInterface, + &Options); - XENBUS_STORE(Free, - &Adapter->StoreInterface, - Buffer); - } else { - Distributions = NULL; - } + RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD)); + Supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; + Supported.Header.Revision = NDIS_OFFLOAD_REVISION_1; + Supported.Header.Size = sizeof(NDIS_OFFLOAD); - if (Distributions == NULL) - goto done; + Supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; - for (Index = 0; Distributions[Index].Buffer != NULL; Index++) { - PANSI_STRING Distribution = &Distributions[Index]; + Supported.Checksum.IPv4Receive.IpChecksum = 1; + Supported.Checksum.IPv4Receive.IpOptionsSupported = 1; - status = XENBUS_STORE(Read, - &Adapter->StoreInterface, - NULL, - "drivers", - Distribution->Buffer, - &Buffer); - if (!NT_SUCCESS(status)) - continue; + Supported.Checksum.IPv4Receive.TcpChecksum = 1; + Supported.Checksum.IPv4Receive.TcpOptionsSupported = 1; - if (__AdapterMatchDistribution(Adapter, Buffer)) - (VOID) XENBUS_STORE(Remove, - &Adapter->StoreInterface, - NULL, - "drivers", - Distribution->Buffer); + Supported.Checksum.IPv4Receive.UdpChecksum = 1; - XENBUS_STORE(Free, - &Adapter->StoreInterface, - Buffer); - } + Supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; - __AdapterFreeAnsi(Distributions); + Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1; -done: - Trace("<====\n"); -} + Supported.Checksum.IPv6Receive.TcpChecksum = 1; + Supported.Checksum.IPv6Receive.TcpOptionsSupported = 1; -#define MAXIMUM_INDEX 255 + Supported.Checksum.IPv6Receive.UdpChecksum = 1; -static FORCEINLINE NTSTATUS -__AdapterSetDistribution( - IN PXENNET_ADAPTER Adapter - ) -{ - ULONG Index; - CHAR Distribution[MAXNAMELEN]; - CHAR Vendor[MAXNAMELEN]; - const CHAR *Product; - NTSTATUS status; + Supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; - Trace("====>\n"); + if (Options.OffloadIpVersion4HeaderChecksum) { + Supported.Checksum.IPv4Transmit.IpChecksum = 1; + Supported.Checksum.IPv4Transmit.IpOptionsSupported = 1; + } - Index = 0; - while (Index <= MAXIMUM_INDEX) { - PCHAR Buffer; + if (Options.OffloadIpVersion4TcpChecksum) { + Supported.Checksum.IPv4Transmit.TcpChecksum = 1; + Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1; + } - status = RtlStringCbPrintfA(Distribution, - MAXNAMELEN, - "%u", - Index); - ASSERT(NT_SUCCESS(status)); + if (Options.OffloadIpVersion4UdpChecksum) + Supported.Checksum.IPv4Transmit.UdpChecksum = 1; - status = XENBUS_STORE(Read, - &Adapter->StoreInterface, - NULL, - "drivers", - Distribution, - &Buffer); - if (!NT_SUCCESS(status)) { - if (status == STATUS_OBJECT_NAME_NOT_FOUND) - goto update; + Supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; + + Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1; - goto fail1; - } + if (Options.OffloadIpVersion6TcpChecksum) { + Supported.Checksum.IPv6Transmit.TcpChecksum = 1; + Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1; + } - XENBUS_STORE(Free, - &Adapter->StoreInterface, - Buffer); + if (Options.OffloadIpVersion6UdpChecksum) + Supported.Checksum.IPv6Transmit.UdpChecksum = 1; - Index++; + if (Options.OffloadIpVersion4LargePacket) { + XENVIF_VIF(TransmitterQueryLargePacketSize, + &Adapter->VifInterface, + 4, + &Supported.LsoV2.IPv4.MaxOffLoadSize); + Supported.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; + Supported.LsoV2.IPv4.MinSegmentCount = 2; } - status = STATUS_UNSUCCESSFUL; - goto fail2; + if (Options.OffloadIpVersion6LargePacket) { + XENVIF_VIF(TransmitterQueryLargePacketSize, + &Adapter->VifInterface, + 6, + &Supported.LsoV2.IPv6.MaxOffLoadSize); + Supported.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3; + Supported.LsoV2.IPv6.MinSegmentCount = 2; + Supported.LsoV2.IPv6.IpExtensionHeadersSupported = 1; + Supported.LsoV2.IPv6.TcpOptionsSupported = 1; + } -update: - status = RtlStringCbPrintfA(Vendor, - MAXNAMELEN, - "%s", - VENDOR_NAME_STR); - ASSERT(NT_SUCCESS(status)); + Default = Supported; - for (Index = 0; Vendor[Index] != '\0'; Index++) - if (!isalnum((UCHAR)Vendor[Index])) - Vendor[Index] = '_'; + if (!(Adapter->Properties.ipv4_csum & 2)) + Default.Checksum.IPv4Receive.IpChecksum = 0; - Product = "XENNET"; + if (!(Adapter->Properties.tcpv4_csum & 2)) + Default.Checksum.IPv4Receive.TcpChecksum = 0; -#if DBG -#define ATTRIBUTES "(DEBUG)" -#else -#define ATTRIBUTES "" -#endif + if (!(Adapter->Properties.udpv4_csum & 2)) + Default.Checksum.IPv4Receive.UdpChecksum = 0; - (VOID) XENBUS_STORE(Printf, - &Adapter->StoreInterface, - NULL, - "drivers", - Distribution, - "%s %s %u.%u.%u %s", - Vendor, - Product, - MAJOR_VERSION, - MINOR_VERSION, - MICRO_VERSION, - ATTRIBUTES - ); + if (!(Adapter->Properties.tcpv6_csum & 2)) + Default.Checksum.IPv6Receive.TcpChecksum = 0; -#undef ATTRIBUTES + if (!(Adapter->Properties.udpv6_csum & 2)) + Default.Checksum.IPv6Receive.UdpChecksum = 0; - Trace("<====\n"); - return STATUS_SUCCESS; + if (!(Adapter->Properties.ipv4_csum & 1)) + Default.Checksum.IPv4Transmit.IpChecksum = 0; -fail2: - Error("fail2\n"); + if (!(Adapter->Properties.tcpv4_csum & 1)) + Default.Checksum.IPv4Transmit.TcpChecksum = 0; -fail1: - Error("fail1 (%08x)\n", status); + if (!(Adapter->Properties.udpv4_csum & 1)) + Default.Checksum.IPv4Transmit.UdpChecksum = 0; - return status; -} + if (!(Adapter->Properties.tcpv6_csum & 1)) + Default.Checksum.IPv6Transmit.TcpChecksum = 0; -static DECLSPEC_NOINLINE VOID -AdapterSuspendCallbackLate( - IN PVOID Argument - ) -{ - PXENNET_ADAPTER Adapter = Argument; + if (!(Adapter->Properties.udpv6_csum & 1)) + Default.Checksum.IPv6Transmit.UdpChecksum = 0; - (VOID) __AdapterSetDistribution(Adapter); -} + if (!(Adapter->Properties.lsov4)) { + Default.LsoV2.IPv4.MaxOffLoadSize = 0; + Default.LsoV2.IPv4.MinSegmentCount = 0; + } -static NTSTATUS -AdapterSetDistribution( - IN PXENNET_ADAPTER Adapter - ) -{ - LONG Count; - NTSTATUS status; + if (!(Adapter->Properties.lsov6)) { + Default.LsoV2.IPv6.MaxOffLoadSize = 0; + Default.LsoV2.IPv6.MinSegmentCount = 0; + } - Trace("====>\n"); + if (!RtlEqualMemory(&Adapter->Offload, &Default, sizeof (NDIS_OFFLOAD))) { + Adapter->Offload = Default; + DISPLAY_OFFLOAD(Default); + } - Count = InterlockedIncrement(&AdapterCount); - ASSERT(Count != 0); + RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES)); + Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES; + Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1; + Attribs.Header.Size = sizeof(Attribs); + Attribs.DefaultOffloadConfiguration = &Default; + Attribs.HardwareOffloadCapabilities = &Supported; - if (Count != 1) - goto done; + ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); + return ndisStatus; +} - status = __AdapterSetDistribution(Adapter); - if (!NT_SUCCESS(status)) - goto fail1; +static NDIS_STATUS +AdapterSetHeaderDataSplitAttributes( + IN PXENNET_ADAPTER Adapter + ) +{ + NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES Attribs; + NDIS_HD_SPLIT_ATTRIBUTES Split; + NDIS_STATUS NdisStatus; - status = XENBUS_SUSPEND(Register, - &Adapter->SuspendInterface, - SUSPEND_CALLBACK_LATE, - AdapterSuspendCallbackLate, - Adapter, - &Adapter->SuspendCallbackLate); - if (!NT_SUCCESS(status)) - goto fail2; + RtlZeroMemory(&Attribs, sizeof(Attribs)); -done: - Trace("<====\n"); - return STATUS_SUCCESS; + Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES; + Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; + Attribs.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1; -fail2: - Error("fail2\n"); + RtlZeroMemory(&Split, sizeof(Split)); - __AdapterClearDistribution(Adapter); + Split.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES; + Split.Header.Revision = NDIS_HD_SPLIT_ATTRIBUTES_REVISION_1; + Split.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1; + Split.HardwareCapabilities = + NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT | + NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS | + NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV6_EXTENSION_HEADERS | + NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS; -fail1: - Error("fail1 (%08x)\n", status); + if (Adapter->Properties.HeaderDataSplit != 0) + Split.CurrentCapabilities = Split.HardwareCapabilities; - return status; -} + Attribs.HDSplitAttributes = &Split; -static VOID -AdapterClearDistribution( - IN PXENNET_ADAPTER Adapter - ) -{ - LONG Count; + NdisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle, + (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs); + if (NdisStatus != NDIS_STATUS_SUCCESS) + goto fail1; - Trace("====>\n"); + if (Split.HDSplitFlags == NDIS_HD_SPLIT_ENABLE_HEADER_DATA_SPLIT) { + ASSERT(Split.CurrentCapabilities & NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT); - Count = InterlockedDecrement(&AdapterCount); + Info("BackfillSize = %u\n", Split.BackfillSize); + Info("MaxHeaderSize = %u\n", Split.MaxHeaderSize); - if (Count != 0) - goto done; + XENVIF_VIF(ReceiverSetBackfillSize, + &Adapter->VifInterface, + Split.BackfillSize); - XENBUS_SUSPEND(Deregister, - &Adapter->SuspendInterface, - Adapter->SuspendCallbackLate); - Adapter->SuspendCallbackLate = NULL; + ReceiverSplitHeaderData(Adapter->Receiver, Split.MaxHeaderSize); + } - __AdapterClearDistribution(Adapter); + return NDIS_STATUS_SUCCESS; -done: - Trace("<====\n"); +fail1: + Error("fail1 (%08x)\n", NdisStatus); + + return NdisStatus; } NDIS_STATUS @@ -2715,52 +2810,35 @@ AdapterInitialize( if (!NT_SUCCESS(status)) goto fail6; - status = XENBUS_CACHE(Acquire, - &(*Adapter)->CacheInterface); - if (!NT_SUCCESS(status)) - 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 fail10; + goto fail7; ndisStatus = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail11; + goto fail8; ndisStatus = AdapterGetAdvancedSettings(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail12; + goto fail9; ndisStatus = AdapterSetRegistrationAttributes(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail13; + goto fail10; ndisStatus = AdapterSetGeneralAttributes(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail14; + goto fail11; ndisStatus = AdapterSetOffloadAttributes(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail15; + goto fail12; ndisStatus = AdapterSetHeaderDataSplitAttributes(*Adapter); if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail16; + goto fail13; RtlZeroMemory(&Dma, sizeof(NDIS_SG_DMA_DESCRIPTION)); Dma.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION; @@ -2777,43 +2855,23 @@ AdapterInitialize( if (ndisStatus != NDIS_STATUS_SUCCESS) (*Adapter)->NdisDmaHandle = NULL; - ndisStatus = AdapterEnable(*Adapter); - if (ndisStatus != NDIS_STATUS_SUCCESS) - goto fail17; - return NDIS_STATUS_SUCCESS; -fail17: - if ((*Adapter)->NdisDmaHandle) - NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle); - (*Adapter)->NdisDmaHandle = NULL; - -fail16: -fail15: -fail14: fail13: fail12: +fail11: +fail10: +fail9: ReceiverTeardown((*Adapter)->Receiver); (*Adapter)->Receiver = NULL; -fail11: +fail8: TransmitterTeardown((*Adapter)->Transmitter); (*Adapter)->Transmitter = NULL; -fail10: +fail7: (*Adapter)->NdisAdapterHandle = NULL; - AdapterClearDistribution(*Adapter); - - XENBUS_SUSPEND(Release, &(*Adapter)->SuspendInterface); - -fail9: - XENBUS_STORE(Release, &(*Adapter)->StoreInterface); - -fail8: - XENBUS_CACHE(Release, &(*Adapter)->CacheInterface); - -fail7: XENVIF_VIF(Release, &(*Adapter)->VifInterface); fail6: @@ -2852,9 +2910,6 @@ AdapterTeardown( 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)); diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h index 3cc1d90..5b2495a 100644 --- a/src/xennet/adapter.h +++ b/src/xennet/adapter.h @@ -99,7 +99,7 @@ AdapterEnable( IN PXENNET_ADAPTER Adapter ); -extern BOOLEAN +extern VOID AdapterDisable( IN PXENNET_ADAPTER Adapter ); diff --git a/src/xennet/miniport.c b/src/xennet/miniport.c index 5500418..1883db5 100644 --- a/src/xennet/miniport.c +++ b/src/xennet/miniport.c @@ -66,7 +66,7 @@ MiniportInitializeEx( PXENNET_ADAPTER Adapter; NDIS_STATUS NdisStatus; - Trace("====>\n"); + Info("====>\n"); UNREFERENCED_PARAMETER(MiniportDriverContext); UNREFERENCED_PARAMETER(MiniportInitParameters); @@ -75,7 +75,7 @@ MiniportInitializeEx( if (NdisStatus != NDIS_STATUS_SUCCESS) goto fail1; - Trace("<====\n"); + Info("<====\n"); return NDIS_STATUS_SUCCESS; @@ -97,16 +97,14 @@ MiniportHaltEx( UNREFERENCED_PARAMETER(HaltAction); - Trace("====>\n"); + Info("====>\n"); if (Adapter == NULL) return; - (VOID) AdapterDisable(Adapter); - AdapterTeardown(Adapter); - Trace("<====\n"); + Info("<====\n"); } static @@ -131,12 +129,11 @@ MiniportPause( UNREFERENCED_PARAMETER(MiniportPauseParameters); - Trace("====>\n"); + Info("====>\n"); - if (AdapterDisable(Adapter)) - AdapterMediaStateChange(Adapter); + AdapterDisable(Adapter); - Trace("<====\n"); + Info("<====\n"); return NDIS_STATUS_SUCCESS; } @@ -154,11 +151,11 @@ MiniportRestart( UNREFERENCED_PARAMETER(MiniportRestartParameters); - Trace("====>\n"); + Info("====>\n"); NdisStatus = AdapterEnable(Adapter); - Trace("<====\n"); + Info("<====\n"); return NdisStatus; } diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c index 17ab27f..8bfc10b 100644 --- a/src/xennet/receiver.c +++ b/src/xennet/receiver.c @@ -359,6 +359,24 @@ fail1: return status; } +NDIS_STATUS +ReceiverEnable ( + IN PXENNET_RECEIVER Receiver + ) +{ + UNREFERENCED_PARAMETER(Receiver); + + return NDIS_STATUS_SUCCESS; +} + +VOID +ReceiverDisable ( + IN PXENNET_RECEIVER Receiver + ) +{ + UNREFERENCED_PARAMETER(Receiver); +} + VOID ReceiverTeardown( IN PXENNET_RECEIVER Receiver diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h index b2cc809..33701a9 100644 --- a/src/xennet/receiver.h +++ b/src/xennet/receiver.h @@ -43,6 +43,16 @@ ReceiverInitialize( OUT PXENNET_RECEIVER *Receiver ); +extern NDIS_STATUS +ReceiverEnable( + IN PXENNET_RECEIVER Receiver + ); + +extern VOID +ReceiverDisable( + IN PXENNET_RECEIVER Receiver + ); + extern VOID ReceiverTeardown( IN PXENNET_RECEIVER Receiver diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c index a617b7d..8c80c7e 100644 --- a/src/xennet/transmitter.c +++ b/src/xennet/transmitter.c @@ -141,16 +141,10 @@ TransmitterInitialize ( OUT PXENNET_TRANSMITTER *Transmitter ) { - NTSTATUS status; - PXENBUS_CACHE_INTERFACE CacheInterface; - - CacheInterface = AdapterGetCacheInterface(Adapter); - *Transmitter = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENNET_TRANSMITTER), TRANSMITTER_POOL_TAG); - status = STATUS_NO_MEMORY; if (*Transmitter == NULL) goto fail1; @@ -160,6 +154,22 @@ TransmitterInitialize ( KeInitializeSpinLock(&(*Transmitter)->Lock); + return NDIS_STATUS_SUCCESS; + +fail1: + return NDIS_STATUS_FAILURE; +} + +NDIS_STATUS +TransmitterEnable ( + IN PXENNET_TRANSMITTER Transmitter + ) +{ + PXENBUS_CACHE_INTERFACE CacheInterface; + NTSTATUS status; + + CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter); + status = XENBUS_CACHE(Create, CacheInterface, "packet_cache", @@ -169,10 +179,10 @@ TransmitterInitialize ( __TransmitterPacketDtor, __TransmitterPacketAcquireLock, __TransmitterPacketReleaseLock, - *Transmitter, - &(*Transmitter)->PacketCache); + Transmitter, + &Transmitter->PacketCache); if (!NT_SUCCESS(status)) - goto fail2; + goto fail1; status = XENBUS_CACHE(Create, CacheInterface, @@ -183,27 +193,20 @@ TransmitterInitialize ( __TransmitterBufferDtor, __TransmitterBufferAcquireLock, __TransmitterBufferReleaseLock, - *Transmitter, - &(*Transmitter)->BufferCache); + Transmitter, + &Transmitter->BufferCache); if (!NT_SUCCESS(status)) - goto fail3; + goto fail2; return NDIS_STATUS_SUCCESS; -fail3: - XENBUS_CACHE(Destroy, - CacheInterface, - (*Transmitter)->PacketCache); - (*Transmitter)->PacketCache = NULL; - fail2: Error("fail2\n"); - RtlZeroMemory(&(*Transmitter)->Lock, sizeof(KSPIN_LOCK)); - - ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG); - - *Transmitter = NULL; + XENBUS_CACHE(Destroy, + CacheInterface, + Transmitter->PacketCache); + Transmitter->PacketCache = NULL; fail1: Error("fail1\n (%08x)", status); @@ -212,7 +215,7 @@ fail1: } VOID -TransmitterTeardown( +TransmitterDisable ( IN PXENNET_TRANSMITTER Transmitter ) { @@ -220,9 +223,6 @@ TransmitterTeardown( CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter); - Transmitter->Adapter = NULL; - Transmitter->OffloadOptions.Value = 0; - XENBUS_CACHE(Destroy, CacheInterface, Transmitter->BufferCache); @@ -232,6 +232,15 @@ TransmitterTeardown( CacheInterface, Transmitter->PacketCache); Transmitter->PacketCache = NULL; +} + +VOID +TransmitterTeardown( + IN PXENNET_TRANSMITTER Transmitter + ) +{ + Transmitter->Adapter = NULL; + Transmitter->OffloadOptions.Value = 0; RtlZeroMemory(&Transmitter->Lock, sizeof(KSPIN_LOCK)); diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h index 0adebdc..363b91e 100644 --- a/src/xennet/transmitter.h +++ b/src/xennet/transmitter.h @@ -43,6 +43,16 @@ TransmitterInitialize( OUT PXENNET_TRANSMITTER *Transmitter ); +extern NDIS_STATUS +TransmitterEnable( + IN PXENNET_TRANSMITTER Transmitter + ); + +extern VOID +TransmitterDisable( + IN PXENNET_TRANSMITTER Transmitter + ); + extern VOID TransmitterTeardown( IN PXENNET_TRANSMITTER Transmitter -- 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 |