win-pvdrivers

annotate xennet/xennet.c @ 1106:2d392ecdd366

Fix race is xenvbd causing 30 second freeze under high load
author James Harper <james.harper@bendigoit.com.au>
date Tue Nov 11 23:08:11 2014 +1100 (2014-11-11)
parents 27bd2a5a4704
children
rev   line source
james@1007 1 /*
james@1099 2 PV Drivers for Windows Xen HVM Domains
james@1007 3
james@1099 4 Copyright (c) 2014, James Harper
james@1099 5 All rights reserved.
james@1007 6
james@1099 7 Redistribution and use in source and binary forms, with or without
james@1099 8 modification, are permitted provided that the following conditions are met:
james@1099 9 * Redistributions of source code must retain the above copyright
james@1099 10 notice, this list of conditions and the following disclaimer.
james@1099 11 * Redistributions in binary form must reproduce the above copyright
james@1099 12 notice, this list of conditions and the following disclaimer in the
james@1099 13 documentation and/or other materials provided with the distribution.
james@1099 14 * Neither the name of James Harper nor the
james@1099 15 names of its contributors may be used to endorse or promote products
james@1099 16 derived from this software without specific prior written permission.
james@1007 17
james@1099 18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
james@1099 19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
james@1099 20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
james@1099 21 DISCLAIMED. IN NO EVENT SHALL JAMES HARPER BE LIABLE FOR ANY
james@1099 22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
james@1099 23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
james@1099 24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
james@1099 25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
james@1099 26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
james@1099 27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
james@1007 28 */
james@1007 29
james@1007 30 #include <stdlib.h>
james@1007 31 #include <io/xenbus.h>
james@1007 32 #include "xennet.h"
james@1007 33
james@1007 34 /* Not really necessary but keeps PREfast happy */
james@1007 35 DRIVER_INITIALIZE DriverEntry;
james@1007 36 #if (VER_PRODUCTBUILD >= 7600)
james@1007 37 static KDEFERRED_ROUTINE XenNet_RxTxDpc;
james@1007 38 #endif
james@1007 39 VOID XenNet_DeviceCallback(PVOID context, ULONG callback_type, PVOID value);
james@1007 40
james@1007 41 #pragma NDIS_INIT_FUNCTION(DriverEntry)
james@1007 42
james@1007 43 NDIS_HANDLE driver_handle = NULL;
james@1007 44
james@1007 45 USHORT ndis_os_major_version = 0;
james@1007 46 USHORT ndis_os_minor_version = 0;
james@1007 47
james@1007 48 static VOID
james@1007 49 XenNet_RxTxDpc(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
james@1007 50 {
james@1007 51 struct xennet_info *xi = context;
james@1007 52 BOOLEAN dont_set_event;
james@1007 53
james@1007 54 UNREFERENCED_PARAMETER(dpc);
james@1007 55 UNREFERENCED_PARAMETER(arg1);
james@1007 56 UNREFERENCED_PARAMETER(arg2);
james@1007 57
james@1007 58 //FUNCTION_ENTER();
james@1007 59 /* if Rx goes over its per-dpc quota then make sure TxBufferGC doesn't set an event as we are already guaranteed to be called again */
james@1007 60 dont_set_event = XenNet_RxBufferCheck(xi);
james@1007 61 XenNet_TxBufferGC(xi, dont_set_event);
james@1007 62 //FUNCTION_EXIT();
james@1007 63 }
james@1007 64
james@1007 65 // Called at PASSIVE_LEVEL
james@1007 66 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 67 static NDIS_STATUS
james@1007 68 XenNet_Init(PNDIS_STATUS open_error_status, PUINT SelectedMediumIndex, PNDIS_MEDIUM MediumArray, UINT MediumArraySize, NDIS_HANDLE adapter_handle, NDIS_HANDLE WrapperConfigurationContext)
james@914 69 #else
james@1007 70 static NDIS_STATUS
james@1007 71 XenNet_Initialize(NDIS_HANDLE adapter_handle, NDIS_HANDLE driver_context, PNDIS_MINIPORT_INIT_PARAMETERS init_parameters)
james@821 72 #endif
james@1007 73 {
james@1007 74 NDIS_STATUS status;
james@1007 75 struct xennet_info *xi = NULL;
james@1007 76 NDIS_HANDLE config_handle;
james@1007 77 PNDIS_CONFIGURATION_PARAMETER config_param;
james@1007 78 NDIS_STRING config_param_name;
james@1007 79 ULONG i;
james@1007 80 //ULONG length;
james@1007 81 PVOID network_address;
james@1007 82 UINT network_address_length;
james@1007 83 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 84 #else
james@1007 85 NDIS_CONFIGURATION_OBJECT config_object;
james@1007 86 NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES registration_attributes;
james@1007 87 NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES general_attributes;
james@1007 88 NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES offload_attributes;
james@1007 89 NDIS_OFFLOAD df_offload, hw_offload;
james@1007 90 NDIS_TCP_CONNECTION_OFFLOAD df_conn_offload, hw_conn_offload;
james@1007 91 NDIS_OID *supported_oids;
james@1007 92 #endif
james@1007 93
james@1007 94 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 95 UNREFERENCED_PARAMETER(open_error_status);
james@1007 96 #else
james@1007 97 UNREFERENCED_PARAMETER(driver_context);
james@1007 98 UNREFERENCED_PARAMETER(init_parameters);
james@1007 99 #endif
james@1007 100
james@1007 101 FUNCTION_ENTER();
james@1007 102
james@1007 103 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 104 for (i = 0; i < MediumArraySize; i++) {
james@1007 105 if (MediumArray[i] == NdisMedium802_3) {
james@1007 106 break;
james@1007 107 }
james@1007 108 }
james@1007 109 if (i == MediumArraySize) {
james@1007 110 FUNCTION_MSG("NIC_MEDIA_TYPE not in MediumArray\n");
james@1007 111 return NDIS_STATUS_UNSUPPORTED_MEDIA;
james@1007 112 }
james@1007 113 *SelectedMediumIndex = i;
james@1007 114 #endif
james@1007 115 /* Alloc memory for adapter private info */
james@1007 116 status = NdisAllocateMemoryWithTag((PVOID)&xi, sizeof(*xi), XENNET_POOL_TAG);
james@1007 117 if (!NT_SUCCESS(status)) {
james@1007 118 FUNCTION_MSG("NdisAllocateMemoryWithTag failed with 0x%x\n", status);
james@1007 119 status = NDIS_STATUS_RESOURCES;
james@1007 120 goto err;
james@1007 121 }
james@1007 122 RtlZeroMemory(xi, sizeof(*xi));
james@1007 123 xi->adapter_handle = adapter_handle;
james@1007 124 xi->device_state = DEVICE_STATE_INITIALISING;
james@1007 125 NdisMGetDeviceProperty(xi->adapter_handle, &xi->pdo, &xi->fdo,
james@1007 126 &xi->lower_do, NULL, NULL);
james@1007 127 KeInitializeEvent(&xi->backend_event, SynchronizationEvent, FALSE);
james@1007 128
james@1007 129 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 130 #endif
james@1067 131 xi->rx_target = RX_DEFAULT_TARGET;
james@1067 132 //xi->rx_min_target = RX_DFL_MIN_TARGET;
james@1067 133 //xi->rx_max_target = RX_MAX_TARGET;
james@1007 134
james@1007 135 xi->multicast_list_size = 0;
james@1007 136 xi->current_lookahead = MIN_LOOKAHEAD_LENGTH;
james@1007 137
james@1007 138 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 139 #else
james@1007 140 xi->stats.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
james@1007 141 xi->stats.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
james@1007 142 xi->stats.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
james@1007 143 xi->stats.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED
james@1007 144 | NDIS_STATISTICS_RCV_OK_SUPPORTED
james@1007 145 | NDIS_STATISTICS_XMIT_ERROR_SUPPORTED
james@1007 146 | NDIS_STATISTICS_RCV_ERROR_SUPPORTED
james@1007 147 | NDIS_STATISTICS_RCV_NO_BUFFER_SUPPORTED
james@1007 148 | NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED
james@1007 149 | NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED
james@1007 150 | NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED
james@1007 151 | NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED
james@1007 152 | NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED
james@1007 153 | NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED
james@1007 154 | NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED
james@1007 155 | NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED
james@1007 156 | NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED
james@1007 157 | NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED
james@1007 158 | NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED
james@1007 159 | NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED
james@1007 160 | NDIS_STATISTICS_RCV_CRC_ERROR_SUPPORTED
james@1007 161 | NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED
james@1007 162 | NDIS_STATISTICS_BYTES_RCV_SUPPORTED
james@1007 163 | NDIS_STATISTICS_BYTES_XMIT_SUPPORTED
james@1007 164 | NDIS_STATISTICS_RCV_DISCARDS_SUPPORTED
james@1007 165 | NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED
james@1007 166 | NDIS_STATISTICS_XMIT_DISCARDS_SUPPORTED;
james@1007 167 #endif
james@1007 168
james@1007 169 KeInitializeDpc(&xi->rxtx_dpc, XenNet_RxTxDpc, xi);
james@1007 170
james@1007 171 xi->packet_filter = 0;
james@1007 172
james@1007 173 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 174 NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
james@1007 175 #else
james@1007 176 config_object.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);
james@1007 177 config_object.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
james@1007 178 config_object.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
james@1007 179 config_object.NdisHandle = xi->adapter_handle;
james@1007 180 config_object.Flags = 0;
james@1007 181
james@1007 182 status = NdisOpenConfigurationEx(&config_object, &config_handle);
james@1007 183 #endif
james@1007 184 if (!NT_SUCCESS(status)) {
james@1007 185 FUNCTION_MSG("Could not open config in registry (%08x)\n", status);
james@1007 186 status = NDIS_STATUS_RESOURCES;
james@1007 187 goto err;
james@1007 188 }
james@1007 189
james@1007 190 NdisInitUnicodeString(&config_param_name, L"ScatterGather");
james@1007 191 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@1070 192 if (!NT_SUCCESS(status))
james@1007 193 {
james@1007 194 FUNCTION_MSG("Could not read ScatterGather value (%08x)\n", status);
james@1007 195 xi->frontend_sg_supported = TRUE;
james@1007 196 } else {
james@1007 197 FUNCTION_MSG("ScatterGather = %d\n", config_param->ParameterData.IntegerData);
james@1013 198 xi->frontend_sg_supported = (BOOLEAN)!!config_param->ParameterData.IntegerData;
james@1007 199 }
james@1007 200 if (xi->frontend_sg_supported && ndis_os_minor_version < 1) {
james@1007 201 FUNCTION_MSG("No support for SG with NDIS 6.0, disabled\n");
james@1007 202 xi->frontend_sg_supported = FALSE;
james@1007 203 }
james@1070 204
james@1070 205 NdisInitUnicodeString(&config_param_name, L"RxCoalesce");
james@1070 206 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@1070 207 if (!NT_SUCCESS(status)) {
james@1070 208 FUNCTION_MSG("Could not read RxCoalesce value (%08x)\n", status);
james@1070 209 xi->config_rx_coalesce = TRUE;
james@1070 210 } else {
james@1070 211 FUNCTION_MSG("RxCoalesce = %d\n", config_param->ParameterData.IntegerData);
james@1070 212 xi->config_rx_coalesce = (BOOLEAN)!!config_param->ParameterData.IntegerData;
james@1070 213 }
james@1007 214
james@1007 215 NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
james@1007 216 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@1007 217 if (!NT_SUCCESS(status)) {
james@1007 218 FUNCTION_MSG("Could not read LargeSendOffload value (%08x)\n", status);
james@1007 219 xi->frontend_gso_value = 0;
james@1007 220 } else {
james@1007 221 FUNCTION_MSG("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData);
james@1007 222 xi->frontend_gso_value = config_param->ParameterData.IntegerData;
james@1007 223 if (xi->frontend_gso_value > 61440) {
james@1007 224 xi->frontend_gso_value = 61440;
james@1007 225 FUNCTION_MSG(" (clipped to %d)\n", xi->frontend_gso_value);
james@1007 226 }
james@1007 227 if (!xi->frontend_sg_supported && xi->frontend_gso_value > PAGE_SIZE - MAX_PKT_HEADER_LENGTH) {
james@1007 228 /* without SG, GSO can be a maximum of PAGE_SIZE - MAX_PKT_HEADER_LENGTH */
james@1007 229 xi->frontend_gso_value = min(xi->frontend_gso_value, PAGE_SIZE - MAX_PKT_HEADER_LENGTH);
james@1007 230 FUNCTION_MSG(" (clipped to %d with sg disabled)\n", xi->frontend_gso_value);
james@1007 231 }
james@1007 232 }
james@1007 233 if (xi->frontend_sg_supported && ndis_os_minor_version < 1) {
james@1007 234 FUNCTION_MSG("No support for GSO with NDIS 6.0, disabled\n");
james@1007 235 xi->frontend_gso_value = 0;
james@1007 236 }
james@1007 237
james@1007 238 NdisInitUnicodeString(&config_param_name, L"LargeSendOffloadRxSplitMTU");
james@1007 239 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@1007 240 if (!NT_SUCCESS(status)) {
james@1007 241 FUNCTION_MSG("Could not read LargeSendOffload value (%08x)\n", status);
james@1007 242 xi->frontend_gso_rx_split_type = RX_LSO_SPLIT_HALF;
james@1007 243 } else {
james@1007 244 FUNCTION_MSG("LargeSendOffloadRxSplitMTU = %d\n", config_param->ParameterData.IntegerData);
james@1007 245 switch (config_param->ParameterData.IntegerData) {
james@1007 246 case RX_LSO_SPLIT_MSS:
james@1007 247 case RX_LSO_SPLIT_HALF:
james@1007 248 case RX_LSO_SPLIT_NONE:
james@1007 249 xi->frontend_gso_rx_split_type = config_param->ParameterData.IntegerData;
james@1007 250 break;
james@1007 251 default:
james@1007 252 xi->frontend_gso_rx_split_type = RX_LSO_SPLIT_HALF;
james@1007 253 break;
james@1007 254 }
james@1007 255 }
james@1007 256
james@1007 257 NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
james@1007 258 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@1007 259 if (!NT_SUCCESS(status)) {
james@1007 260 FUNCTION_MSG("Could not read ChecksumOffload value (%08x)\n", status);
james@1007 261 xi->frontend_csum_supported = TRUE;
james@1007 262 } else {
james@1007 263 FUNCTION_MSG("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData);
james@1013 264 xi->frontend_csum_supported = (BOOLEAN)!!config_param->ParameterData.IntegerData;
james@1007 265 }
james@1007 266
james@1007 267 NdisInitUnicodeString(&config_param_name, L"MTU");
james@1007 268 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@1007 269 if (!NT_SUCCESS(status)) {
james@1007 270 FUNCTION_MSG("Could not read MTU value (%08x)\n", status);
james@1007 271 xi->frontend_mtu_value = 1500;
james@1007 272 } else {
james@1007 273 FUNCTION_MSG("MTU = %d\n", config_param->ParameterData.IntegerData);
james@1007 274 xi->frontend_mtu_value = config_param->ParameterData.IntegerData;
james@1007 275 }
james@1007 276
james@1007 277 NdisReadNetworkAddress(&status, &network_address, &network_address_length, config_handle);
james@1007 278 if (!NT_SUCCESS(status) || network_address_length != ETH_ALEN || ((((PUCHAR)network_address)[0] & 0x03) != 0x02)) {
james@1007 279 FUNCTION_MSG("Could not read registry NetworkAddress value (%08x) or value is invalid\n", status);
james@1007 280 memset(xi->curr_mac_addr, 0, ETH_ALEN);
james@1007 281 } else {
james@1007 282 memcpy(xi->curr_mac_addr, network_address, ETH_ALEN);
james@1007 283 FUNCTION_MSG("Set MAC address from registry to %02X:%02X:%02X:%02X:%02X:%02X\n",
james@1007 284 xi->curr_mac_addr[0], xi->curr_mac_addr[1], xi->curr_mac_addr[2],
james@1007 285 xi->curr_mac_addr[3], xi->curr_mac_addr[4], xi->curr_mac_addr[5]);
james@1007 286 }
james@1007 287
james@1007 288 NdisCloseConfiguration(config_handle);
james@1007 289
james@1052 290 status = XenNet_Connect(xi, FALSE);
james@1052 291 if (!NT_SUCCESS(status)) {
james@1052 292 goto err;
james@1052 293 }
james@1007 294
james@1007 295 if (!xi->backend_sg_supported)
james@1007 296 xi->backend_gso_value = min(xi->backend_gso_value, PAGE_SIZE - MAX_PKT_HEADER_LENGTH);
james@1007 297
james@1007 298 xi->current_sg_supported = xi->frontend_sg_supported && xi->backend_sg_supported;
james@1007 299 xi->current_mtu_value = xi->frontend_mtu_value;
james@1007 300 xi->current_gso_rx_split_type = xi->frontend_gso_rx_split_type;
james@1007 301
james@1007 302 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 303 /* these are set by OID for NDIS5 */
james@1007 304 xi->current_csum_supported = FALSE;
james@1007 305 xi->current_gso_value = 0;
james@1007 306 xi->config_max_pkt_size = xi->current_mtu_value + XN_HDR_SIZE;
james@1007 307 #else
james@1007 308 xi->current_csum_supported = xi->frontend_csum_supported && xi->backend_csum_supported;
james@1007 309 xi->current_gso_value = min(xi->backend_gso_value, xi->backend_gso_value);
james@1007 310 xi->config_max_pkt_size = max(xi->current_mtu_value + XN_HDR_SIZE, xi->current_gso_value + XN_HDR_SIZE);
james@1007 311 #endif
james@1007 312
james@1007 313 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 314 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE)xi, 0, 0 /* the last zero is to give the next | something to | with */
james@1007 315 #ifdef NDIS51_MINIPORT
james@1007 316 |NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
james@1007 317 #endif
james@1007 318 |NDIS_ATTRIBUTE_DESERIALIZE
james@1007 319 |NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK,
james@1007 320 NdisInterfaceInternal); /* PnpBus option doesn't exist... */
james@1007 321 #else
james@1007 322 registration_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
james@1007 323 registration_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
james@1007 324 registration_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
james@1007 325 registration_attributes.MiniportAdapterContext = xi;
james@1007 326 registration_attributes.AttributeFlags = 0;
james@1007 327 registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE;
james@1007 328 registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK;
james@1007 329 registration_attributes.CheckForHangTimeInSeconds = 0; /* use default */
james@1007 330 registration_attributes.InterfaceType = NdisInterfacePNPBus;
james@1007 331 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registration_attributes);
james@1007 332 if (!NT_SUCCESS(status)) {
james@1007 333 FUNCTION_MSG("NdisMSetMiniportAttributes(registration) failed (%08x)\n", status);
james@1007 334 goto err;
james@1007 335 }
james@1007 336
james@1007 337 general_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
james@1007 338 general_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; /* revision 2 is NDIS 6.2 */
james@1007 339 general_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
james@1007 340 general_attributes.Flags = 0;
james@1007 341 general_attributes.MediaType = NdisMedium802_3;
james@1007 342 general_attributes.PhysicalMediumType = NdisPhysicalMediumOther;
james@1007 343 general_attributes.MtuSize = xi->current_mtu_value;
james@1007 344 general_attributes.MaxXmitLinkSpeed = MAX_LINK_SPEED;
james@1007 345 general_attributes.XmitLinkSpeed = MAX_LINK_SPEED;
james@1007 346 general_attributes.MaxRcvLinkSpeed = MAX_LINK_SPEED;
james@1007 347 general_attributes.RcvLinkSpeed = MAX_LINK_SPEED;
james@1007 348 general_attributes.MediaConnectState = MediaConnectStateConnected;
james@1007 349 general_attributes.MediaDuplexState = MediaDuplexStateFull;
james@1007 350 general_attributes.LookaheadSize = xi->current_lookahead;
james@1007 351 general_attributes.PowerManagementCapabilities = NULL;
james@1007 352 general_attributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
james@1007 353 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
james@1007 354 NDIS_MAC_OPTION_NO_LOOPBACK;
james@1007 355 general_attributes.SupportedPacketFilters = SUPPORTED_PACKET_FILTERS;
james@1007 356 general_attributes.MaxMulticastListSize = MULTICAST_LIST_MAX_SIZE;
james@1007 357 general_attributes.MacAddressLength = 6;
james@1007 358 NdisMoveMemory(general_attributes.PermanentMacAddress, xi->perm_mac_addr, general_attributes.MacAddressLength);
james@1007 359 NdisMoveMemory(general_attributes.CurrentMacAddress, xi->curr_mac_addr, general_attributes.MacAddressLength);
james@1007 360 general_attributes.RecvScaleCapabilities = NULL; /* we do want to support this soon */
james@1007 361 general_attributes.AccessType = NET_IF_ACCESS_BROADCAST;
james@1007 362 general_attributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
james@1007 363 general_attributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;
james@1007 364 general_attributes.IfType = IF_TYPE_ETHERNET_CSMACD;
james@1007 365 general_attributes.IfConnectorPresent = TRUE;
james@1007 366 general_attributes.SupportedStatistics = xi->stats.SupportedStatistics;
james@1007 367 general_attributes.SupportedPauseFunctions = NdisPauseFunctionsUnsupported;
james@1007 368 general_attributes.DataBackFillSize = 0; // see NdisRetreatNetBufferDataStart
james@1007 369 general_attributes.ContextBackFillSize = 0; // ?? NFI ??
james@1007 370
james@1007 371 for (i = 0; xennet_oids[i].oid; i++);
james@1007 372
james@1007 373 status = NdisAllocateMemoryWithTag((PVOID)&supported_oids, sizeof(NDIS_OID) * i, XENNET_POOL_TAG);
james@1007 374 if (!NT_SUCCESS(status)) {
james@1007 375 FUNCTION_MSG("NdisAllocateMemoryWithTag failed with 0x%x\n", status);
james@1007 376 status = NDIS_STATUS_RESOURCES;
james@1007 377 goto err;
james@1007 378 }
james@1007 379
james@1007 380 for (i = 0; xennet_oids[i].oid; i++) {
james@1007 381 supported_oids[i] = xennet_oids[i].oid;
james@1007 382 FUNCTION_MSG("Supporting %08x (%s) %s %d bytes\n", xennet_oids[i].oid, xennet_oids[i].oid_name, (xennet_oids[i].query_routine?(xennet_oids[i].set_routine?"get/set":"get only"):(xennet_oids[i].set_routine?"set only":"none")), xennet_oids[i].min_length);
james@1007 383 }
james@1007 384 general_attributes.SupportedOidList = supported_oids;
james@1007 385 general_attributes.SupportedOidListLength = sizeof(NDIS_OID) * i;
james@1007 386 general_attributes.AutoNegotiationFlags = NDIS_LINK_STATE_XMIT_LINK_SPEED_AUTO_NEGOTIATED
james@1007 387 | NDIS_LINK_STATE_RCV_LINK_SPEED_AUTO_NEGOTIATED
james@1007 388 | NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;
james@1007 389 //general_attributes.PowerManagementCapabilitiesEx = NULL; // >= 6.20
james@1007 390 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&general_attributes);
james@1007 391 if (!NT_SUCCESS(status)) {
james@1007 392 FUNCTION_MSG("NdisMSetMiniportAttributes(general) failed (%08x)\n", status);
james@1007 393 goto err;
james@1007 394 }
james@1007 395 NdisFreeMemory(supported_oids, 0, 0);
james@1007 396
james@1007 397 /* this is the initial offload state */
james@1007 398 RtlZeroMemory(&df_offload, sizeof(df_offload));
james@1007 399 df_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
james@1007 400 df_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
james@1007 401 df_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
james@1007 402 /* this is the supported offload state */
james@1007 403 RtlZeroMemory(&hw_offload, sizeof(hw_offload));
james@1007 404 hw_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
james@1007 405 hw_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
james@1007 406 hw_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
james@1007 407 if (xi->current_csum_supported)
james@1007 408 {
james@1007 409 df_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 410 df_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
james@1007 411 df_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
james@1007 412 df_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SET_ON;
james@1007 413 df_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SET_ON;
james@1007 414 df_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SET_ON;
james@1007 415 df_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 416 df_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
james@1007 417 df_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
james@1007 418 df_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SET_ON;
james@1007 419 df_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SET_ON;
james@1007 420 df_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SET_ON;
james@1007 421 /* offload.Checksum.IPv6Transmit is not supported */
james@1007 422 /* offload.Checksum.IPv6Receive is not supported */
james@1007 423 hw_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 424 hw_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
james@1007 425 hw_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
james@1007 426 hw_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
james@1007 427 hw_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
james@1007 428 hw_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
james@1007 429 hw_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 430 hw_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
james@1007 431 hw_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
james@1007 432 hw_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
james@1007 433 hw_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
james@1007 434 hw_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
james@1007 435 /* hw_offload.Checksum.IPv6Transmit is not supported */
james@1007 436 /* hw_offload.Checksum.IPv6Receive is not supported */
james@1007 437 }
james@1007 438 if (xi->current_gso_value)
james@1007 439 {
james@1007 440 hw_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 441 hw_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
james@1007 442 hw_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
james@1007 443 hw_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
james@1007 444 hw_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
james@1007 445 hw_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 446 hw_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
james@1007 447 hw_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
james@1007 448 /* hw_offload.LsoV2.IPv6 is not supported */
james@1007 449 df_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 450 df_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
james@1007 451 df_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
james@1007 452 df_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
james@1007 453 df_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
james@1007 454 df_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
james@1007 455 df_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
james@1007 456 df_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
james@1007 457 /* df_offload.LsoV2.IPv6 is not supported */
james@1007 458 }
james@1007 459 /* hw_offload.IPsecV1 is not supported */
james@1007 460 /* hw_offload.IPsecV2 is not supported */
james@1007 461 /* df_offload.IPsecV1 is not supported */
james@1007 462 /* df_offload.IPsecV2 is not supported */
james@1007 463 hw_offload.Flags = 0;
james@1007 464 df_offload.Flags = 0;
james@1007 465
james@1007 466 RtlZeroMemory(&df_conn_offload, sizeof(df_conn_offload));
james@1007 467 df_conn_offload.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
james@1007 468 df_conn_offload.Header.Revision = NDIS_TCP_CONNECTION_OFFLOAD_REVISION_1;
james@1007 469 df_conn_offload.Header.Size = NDIS_SIZEOF_TCP_CONNECTION_OFFLOAD_REVISION_1;
james@1007 470
james@1007 471 RtlZeroMemory(&hw_conn_offload, sizeof(hw_conn_offload));
james@1007 472 hw_conn_offload.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
james@1007 473 hw_conn_offload.Header.Revision = NDIS_TCP_CONNECTION_OFFLOAD_REVISION_1;
james@1007 474 hw_conn_offload.Header.Size = NDIS_SIZEOF_TCP_CONNECTION_OFFLOAD_REVISION_1;
james@1007 475
james@1007 476 offload_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
james@1007 477 offload_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
james@1007 478 offload_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
james@1007 479 offload_attributes.DefaultOffloadConfiguration = &df_offload;
james@1007 480 offload_attributes.HardwareOffloadCapabilities = &hw_offload;
james@1007 481 offload_attributes.DefaultTcpConnectionOffloadConfiguration = &df_conn_offload;
james@1007 482 offload_attributes.TcpConnectionOffloadHardwareCapabilities = &hw_conn_offload;
james@1007 483 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offload_attributes);
james@1007 484 if (!NT_SUCCESS(status)) {
james@1007 485 FUNCTION_MSG("NdisMSetMiniportAttributes(offload) failed (%08x)\n", status);
james@1007 486 goto err;
james@1007 487 }
james@1007 488
james@1007 489 #if 0
james@1007 490 if (ndis_os_minor_version >= 1) {
james@1007 491 NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES hw_assist_attributes;
james@1007 492 NDIS_HD_SPLIT_ATTRIBUTES hd_split_attributes;
james@1007 493
james@1007 494 RtlZeroMemory(&hd_split_attributes, sizeof(hd_split_attributes));
james@1007 495 hd_split_attributes.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;
james@1007 496 hd_split_attributes.Header.Revision = NDIS_HD_SPLIT_ATTRIBUTES_REVISION_1;
james@1007 497 hd_split_attributes.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;
james@1007 498 hd_split_attributes.HardwareCapabilities = NDIS_HD_SPLIT_CAPS_SUPPORTS_HEADER_DATA_SPLIT | NDIS_HD_SPLIT_CAPS_SUPPORTS_IPV4_OPTIONS | NDIS_HD_SPLIT_CAPS_SUPPORTS_TCP_OPTIONS;
james@1007 499 hd_split_attributes.CurrentCapabilities = hd_split_attributes.HardwareCapabilities;
james@1007 500 /* the other members are set on output */
james@1007 501
james@1007 502 RtlZeroMemory(&hw_assist_attributes, sizeof(hw_assist_attributes));
james@1007 503 hw_assist_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;
james@1007 504 hw_assist_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
james@1007 505 hw_assist_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
james@1007 506 hw_assist_attributes.HDSplitAttributes = &hd_split_attributes;
james@1007 507 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&hw_assist_attributes);
james@1007 508 if (!NT_SUCCESS(status))
james@1007 509 {
james@1007 510 FUNCTION_MSG("NdisMSetMiniportAttributes(hw_assist) failed (%08x)\n", status);
james@1007 511 goto err;
james@1007 512 }
james@1007 513 FUNCTION_MSG("HW Split enabled\n");
james@1007 514 FUNCTION_MSG(" HDSplitFlags = %08x\n", hd_split_attributes.HDSplitFlags);
james@1007 515 FUNCTION_MSG(" BackfillSize = %d\n", hd_split_attributes.BackfillSize);
james@1007 516 FUNCTION_MSG(" MaxHeaderSize = %d\n", hd_split_attributes.MaxHeaderSize);
james@1007 517 //what about backfill here?
james@1007 518 }
james@1007 519 #endif
james@1007 520 #endif
james@1007 521 if (xi->device_state != DEVICE_STATE_INACTIVE)
james@1007 522 xi->device_state = DEVICE_STATE_ACTIVE;
james@1007 523 FUNCTION_EXIT();
james@1007 524 return NDIS_STATUS_SUCCESS;
james@1007 525
james@1007 526 err:
james@1007 527 if (xi) {
james@1007 528 NdisFreeMemory(xi, 0, 0);
james@1007 529 }
james@1007 530 FUNCTION_EXIT_STATUS(status);
james@1007 531
james@1007 532 return status;
james@1007 533 }
james@1007 534
james@1007 535 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 536 static VOID
james@1007 537 XenNet_PnPEventNotify(NDIS_HANDLE adapter_context, NDIS_DEVICE_PNP_EVENT pnp_event, PVOID information_buffer, ULONG information_buffer_length) {
james@1007 538 UNREFERENCED_PARAMETER(information_buffer);
james@1007 539 UNREFERENCED_PARAMETER(information_buffer_length);
james@1007 540 UNREFERENCED_PARAMETER(adapter_context);
james@1007 541
james@1007 542 FUNCTION_ENTER();
james@1007 543 switch (pnp_event)
james@1007 544 {
james@1007 545 case NdisDevicePnPEventSurpriseRemoved:
james@1007 546 FUNCTION_MSG("NdisDevicePnPEventSurpriseRemoved\n");
james@1007 547 break;
james@1007 548 case NdisDevicePnPEventPowerProfileChanged :
james@1007 549 FUNCTION_MSG("NdisDevicePnPEventPowerProfileChanged\n");
james@1007 550 break;
james@1007 551 default:
james@1007 552 FUNCTION_MSG("NdisDevicePnPEvent%d\n", pnp_event);
james@1007 553 break;
james@1007 554 }
james@1007 555 FUNCTION_EXIT();
james@1007 556 }
james@1007 557 #else
james@1007 558 static VOID
james@1007 559 XenNet_DevicePnPEventNotify(NDIS_HANDLE adapter_context, PNET_DEVICE_PNP_EVENT pnp_event) {
james@1007 560 UNREFERENCED_PARAMETER(adapter_context);
james@1007 561
james@1007 562 FUNCTION_ENTER();
james@1007 563 switch (pnp_event->DevicePnPEvent)
james@1007 564 {
james@1007 565 case NdisDevicePnPEventSurpriseRemoved:
james@1007 566 FUNCTION_MSG("NdisDevicePnPEventSurpriseRemoved\n");
james@1007 567 break;
james@1007 568 case NdisDevicePnPEventPowerProfileChanged :
james@1007 569 FUNCTION_MSG("NdisDevicePnPEventPowerProfileChanged\n");
james@1007 570 break;
james@1007 571 default:
james@1007 572 FUNCTION_MSG("NdisDevicePnPEvent%d\n", pnp_event->DevicePnPEvent);
james@1007 573 break;
james@1007 574 }
james@1007 575 FUNCTION_EXIT();
james@1007 576 }
james@1007 577 #endif
james@1007 578
james@1007 579 /* called at <= HIGH_IRQL, or PASSIVE_LEVEL, depending on shutdown_action */
james@1007 580 static VOID
james@1007 581 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 582 XenNet_Shutdown(NDIS_HANDLE adapter_context) {
james@1007 583 #else
james@1007 584 XenNet_Shutdown(NDIS_HANDLE adapter_context, NDIS_SHUTDOWN_ACTION shutdown_action) {
james@1007 585 UNREFERENCED_PARAMETER(shutdown_action);
james@1007 586 #endif
james@1007 587 UNREFERENCED_PARAMETER(adapter_context);
james@1007 588 FUNCTION_ENTER();
james@1007 589 FUNCTION_EXIT();
james@1007 590 }
james@1007 591
james@1007 592 static BOOLEAN
james@1007 593 XenNet_CheckForHang(NDIS_HANDLE adapter_context)
james@1007 594 {
james@1007 595 UNREFERENCED_PARAMETER(adapter_context);
james@1007 596
james@1007 597 //FUNCTION_ENTER();
james@1007 598 //FUNCTION_EXIT();
james@1007 599 return FALSE;
james@1007 600 }
james@1007 601
james@1007 602 /* Opposite of XenNet_Init */
james@1007 603 static VOID
james@1007 604 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 605 XenNet_Halt(NDIS_HANDLE adapter_context) {
james@1007 606 #else
james@1007 607 XenNet_Halt(NDIS_HANDLE adapter_context, NDIS_HALT_ACTION halt_action) {
james@1007 608 #endif
james@1007 609 struct xennet_info *xi = adapter_context;
james@1007 610 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 611 #else
james@1007 612 UNREFERENCED_PARAMETER(halt_action);
james@1007 613 #endif
james@1007 614 FUNCTION_ENTER();
james@1007 615 XenNet_Disconnect(xi, FALSE);
james@1007 616 NdisFreeMemory(xi, 0, 0);
james@1007 617
james@1007 618 FUNCTION_EXIT();
james@1007 619 }
james@1007 620
james@1007 621 static NDIS_STATUS
james@1007 622 XenNet_Reset(NDIS_HANDLE adapter_context, PBOOLEAN addressing_reset)
james@1007 623 {
james@1007 624 UNREFERENCED_PARAMETER(adapter_context);
james@1007 625
james@1007 626 FUNCTION_ENTER();
james@1007 627 *addressing_reset = FALSE;
james@1007 628 FUNCTION_EXIT();
james@1007 629 return NDIS_STATUS_SUCCESS;
james@1007 630 }
james@1007 631
james@1007 632 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 633 #else
james@1007 634 /* called at PASSIVE_LEVEL */
james@1007 635 static NDIS_STATUS
james@1007 636 XenNet_Pause(NDIS_HANDLE adapter_context, PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters)
james@1007 637 {
james@1007 638 UNREFERENCED_PARAMETER(adapter_context);
james@1007 639 UNREFERENCED_PARAMETER(pause_parameters);
james@1007 640 FUNCTION_ENTER();
james@1007 641 FUNCTION_EXIT();
james@1007 642 return STATUS_SUCCESS;
james@1007 643 }
james@1007 644
james@1007 645 /* called at PASSIVE_LEVEL */
james@1007 646 static NDIS_STATUS
james@1007 647 XenNet_Restart(NDIS_HANDLE adapter_context, PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters)
james@1007 648 {
james@1007 649 UNREFERENCED_PARAMETER(adapter_context);
james@1007 650 UNREFERENCED_PARAMETER(restart_parameters);
james@1007 651 FUNCTION_ENTER();
james@1007 652 FUNCTION_EXIT();
james@1007 653 return STATUS_SUCCESS;
james@1007 654 }
james@1007 655
james@1007 656 static VOID
james@1007 657 XenNet_Unload(PDRIVER_OBJECT driver_object)
james@1007 658 {
james@1007 659 UNREFERENCED_PARAMETER(driver_object);
james@1007 660 FUNCTION_ENTER();
james@1007 661 NdisMDeregisterMiniportDriver(driver_handle);
james@1007 662 FUNCTION_EXIT();
james@1007 663 }
james@1007 664
james@1007 665 static NDIS_STATUS
james@1007 666 XenNet_SetOptions(NDIS_HANDLE driver_handle, NDIS_HANDLE driver_context)
james@1007 667 {
james@1007 668 UNREFERENCED_PARAMETER(driver_handle);
james@1007 669 UNREFERENCED_PARAMETER(driver_context);
james@1007 670 FUNCTION_ENTER();
james@1007 671 FUNCTION_EXIT();
james@1007 672 return STATUS_SUCCESS;
james@1007 673 }
james@1007 674 #endif
james@1007 675
james@1007 676 NTSTATUS
james@1007 677 DriverEntry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path)
james@1007 678 {
james@1007 679 NTSTATUS status;
james@1007 680 ULONG ndis_version;
james@1007 681 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 682 NDIS_HANDLE ndis_wrapper_handle = NULL;
james@1007 683 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
james@1007 684 #else
james@1007 685 NDIS_MINIPORT_DRIVER_CHARACTERISTICS mini_chars;
james@1007 686 #endif
james@1007 687
james@1007 688 FUNCTION_ENTER();
james@1007 689
james@1007 690 NdisZeroMemory(&mini_chars, sizeof(mini_chars));
james@1007 691
james@1007 692 ndis_version = NdisGetVersion();
james@1007 693
james@1013 694 ndis_os_major_version = (USHORT)(ndis_version >> 16);
james@1013 695 ndis_os_minor_version = (USHORT)(ndis_version & 0xFFFF);
james@1007 696
james@1007 697 FUNCTION_MSG("Driver MajorNdisVersion = %d, Driver MinorNdisVersion = %d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION);
james@1007 698 FUNCTION_MSG("Windows MajorNdisVersion = %d, Windows MinorNdisVersion = %d\n", ndis_os_major_version, ndis_os_minor_version);
james@1007 699
james@1007 700 #if NTDDI_VERSION < NTDDI_VISTA
james@1007 701 NdisMInitializeWrapper(&ndis_wrapper_handle, driver_object, registry_path, NULL);
james@1007 702 if (!ndis_wrapper_handle) {
james@1007 703 FUNCTION_MSG("NdisMInitializeWrapper failed\n");
james@1007 704 return NDIS_STATUS_FAILURE;
james@1007 705 }
james@1007 706
james@1007 707 mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
james@1007 708 mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
james@1007 709 mini_chars.HaltHandler = XenNet_Halt;
james@1007 710 mini_chars.InitializeHandler = XenNet_Init;
james@1007 711 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
james@1007 712 mini_chars.ResetHandler = XenNet_Reset;
james@1007 713 mini_chars.SetInformationHandler = XenNet_SetInformation;
james@1007 714 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
james@1007 715 mini_chars.SendPacketsHandler = XenNet_SendPackets;
james@1007 716 #ifdef NDIS51_MINIPORT
james@1007 717 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
james@1007 718 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
james@1007 719 #endif
james@1007 720 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
james@1007 721 if (!NT_SUCCESS(status)) {
james@1007 722 FUNCTION_MSG("NdisMRegisterMiniport failed, status = 0x%x\n", status);
james@1007 723 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
james@1007 724 return status;
james@1007 725 }
james@1007 726 #else
james@1007 727 mini_chars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
james@1007 728
james@1007 729 if (ndis_os_minor_version < 1) {
james@1007 730 mini_chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
james@1007 731 mini_chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
james@1007 732
james@1007 733 mini_chars.MajorNdisVersion = 6;
james@1007 734 mini_chars.MinorNdisVersion = 0;
james@1007 735 } else {
james@1007 736 mini_chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
james@1007 737 mini_chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
james@1007 738 mini_chars.MajorNdisVersion = 6;
james@1007 739 mini_chars.MinorNdisVersion = 1;
james@1007 740 }
james@1007 741 mini_chars.MajorDriverVersion = VENDOR_DRIVER_VERSION_MAJOR;
james@1007 742 mini_chars.MinorDriverVersion = VENDOR_DRIVER_VERSION_MINOR;
james@1007 743
james@1007 744 mini_chars.Flags = NDIS_WDM_DRIVER;
james@1007 745
james@1007 746 mini_chars.SetOptionsHandler = XenNet_SetOptions;
james@1007 747 mini_chars.InitializeHandlerEx = XenNet_Initialize;
james@1007 748 mini_chars.HaltHandlerEx = XenNet_Halt;
james@1007 749 mini_chars.UnloadHandler = XenNet_Unload;
james@1007 750 mini_chars.PauseHandler = XenNet_Pause;
james@1007 751 mini_chars.RestartHandler = XenNet_Restart;
james@1007 752 mini_chars.CheckForHangHandlerEx = XenNet_CheckForHang;
james@1007 753 mini_chars.ResetHandlerEx = XenNet_Reset;
james@1007 754 mini_chars.DevicePnPEventNotifyHandler = XenNet_DevicePnPEventNotify;
james@1007 755 mini_chars.ShutdownHandlerEx = XenNet_Shutdown;
james@1007 756
james@1007 757 mini_chars.OidRequestHandler = XenNet_OidRequest;
james@1007 758 mini_chars.CancelOidRequestHandler = XenNet_CancelOidRequest;
james@1007 759 if (ndis_os_minor_version >= 1) {
james@1007 760 mini_chars.DirectOidRequestHandler = NULL;
james@1007 761 mini_chars.CancelDirectOidRequestHandler = NULL;
james@1007 762 }
james@1007 763
james@1007 764 mini_chars.SendNetBufferListsHandler = XenNet_SendNetBufferLists;
james@1011 765 mini_chars.CancelSendHandler = XenNet_CancelSend;
james@1007 766
james@1007 767 mini_chars.ReturnNetBufferListsHandler = XenNet_ReturnNetBufferLists;
james@1007 768
james@1007 769 status = NdisMRegisterMiniportDriver(driver_object, registry_path, NULL, &mini_chars, &driver_handle);
james@1007 770 if (!NT_SUCCESS(status)) {
james@1007 771 FUNCTION_MSG("NdisMRegisterMiniportDriver failed, status = 0x%x\n", status);
james@1007 772 return status;
james@1007 773 }
james@1007 774 #endif
james@1007 775 FUNCTION_EXIT();
james@1007 776
james@1007 777 return status;
james@1007 778 }