win-pvdrivers

view xennet/xennet.c @ 1070:05ece536b204

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