win-pvdrivers

view xennet/xennet.c @ 1067:2ef536c2d9fe

Fix packet exhaustion issue in 2003 where windows doesn't return packets
author James Harper <james.harper@bendigoit.com.au>
date Tue Oct 29 19:39:52 2013 +1100 (2013-10-29)
parents 5bb1f345e06a
children 05ece536b204
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"LargeSendOffload");
197 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
198 if (!NT_SUCCESS(status)) {
199 FUNCTION_MSG("Could not read LargeSendOffload value (%08x)\n", status);
200 xi->frontend_gso_value = 0;
201 } else {
202 FUNCTION_MSG("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData);
203 xi->frontend_gso_value = config_param->ParameterData.IntegerData;
204 if (xi->frontend_gso_value > 61440) {
205 xi->frontend_gso_value = 61440;
206 FUNCTION_MSG(" (clipped to %d)\n", xi->frontend_gso_value);
207 }
208 if (!xi->frontend_sg_supported && xi->frontend_gso_value > PAGE_SIZE - MAX_PKT_HEADER_LENGTH) {
209 /* without SG, GSO can be a maximum of PAGE_SIZE - MAX_PKT_HEADER_LENGTH */
210 xi->frontend_gso_value = min(xi->frontend_gso_value, PAGE_SIZE - MAX_PKT_HEADER_LENGTH);
211 FUNCTION_MSG(" (clipped to %d with sg disabled)\n", xi->frontend_gso_value);
212 }
213 }
214 if (xi->frontend_sg_supported && ndis_os_minor_version < 1) {
215 FUNCTION_MSG("No support for GSO with NDIS 6.0, disabled\n");
216 xi->frontend_gso_value = 0;
217 }
219 NdisInitUnicodeString(&config_param_name, L"LargeSendOffloadRxSplitMTU");
220 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
221 if (!NT_SUCCESS(status)) {
222 FUNCTION_MSG("Could not read LargeSendOffload value (%08x)\n", status);
223 xi->frontend_gso_rx_split_type = RX_LSO_SPLIT_HALF;
224 } else {
225 FUNCTION_MSG("LargeSendOffloadRxSplitMTU = %d\n", config_param->ParameterData.IntegerData);
226 switch (config_param->ParameterData.IntegerData) {
227 case RX_LSO_SPLIT_MSS:
228 case RX_LSO_SPLIT_HALF:
229 case RX_LSO_SPLIT_NONE:
230 xi->frontend_gso_rx_split_type = config_param->ParameterData.IntegerData;
231 break;
232 default:
233 xi->frontend_gso_rx_split_type = RX_LSO_SPLIT_HALF;
234 break;
235 }
236 }
238 NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
239 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
240 if (!NT_SUCCESS(status)) {
241 FUNCTION_MSG("Could not read ChecksumOffload value (%08x)\n", status);
242 xi->frontend_csum_supported = TRUE;
243 } else {
244 FUNCTION_MSG("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData);
245 xi->frontend_csum_supported = (BOOLEAN)!!config_param->ParameterData.IntegerData;
246 }
248 NdisInitUnicodeString(&config_param_name, L"MTU");
249 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
250 if (!NT_SUCCESS(status)) {
251 FUNCTION_MSG("Could not read MTU value (%08x)\n", status);
252 xi->frontend_mtu_value = 1500;
253 } else {
254 FUNCTION_MSG("MTU = %d\n", config_param->ParameterData.IntegerData);
255 xi->frontend_mtu_value = config_param->ParameterData.IntegerData;
256 }
258 NdisReadNetworkAddress(&status, &network_address, &network_address_length, config_handle);
259 if (!NT_SUCCESS(status) || network_address_length != ETH_ALEN || ((((PUCHAR)network_address)[0] & 0x03) != 0x02)) {
260 FUNCTION_MSG("Could not read registry NetworkAddress value (%08x) or value is invalid\n", status);
261 memset(xi->curr_mac_addr, 0, ETH_ALEN);
262 } else {
263 memcpy(xi->curr_mac_addr, network_address, ETH_ALEN);
264 FUNCTION_MSG("Set MAC address from registry to %02X:%02X:%02X:%02X:%02X:%02X\n",
265 xi->curr_mac_addr[0], xi->curr_mac_addr[1], xi->curr_mac_addr[2],
266 xi->curr_mac_addr[3], xi->curr_mac_addr[4], xi->curr_mac_addr[5]);
267 }
269 NdisCloseConfiguration(config_handle);
271 status = XenNet_Connect(xi, FALSE);
272 if (!NT_SUCCESS(status)) {
273 goto err;
274 }
276 if (!xi->backend_sg_supported)
277 xi->backend_gso_value = min(xi->backend_gso_value, PAGE_SIZE - MAX_PKT_HEADER_LENGTH);
279 xi->current_sg_supported = xi->frontend_sg_supported && xi->backend_sg_supported;
280 xi->current_mtu_value = xi->frontend_mtu_value;
281 xi->current_gso_rx_split_type = xi->frontend_gso_rx_split_type;
283 #if NTDDI_VERSION < NTDDI_VISTA
284 /* these are set by OID for NDIS5 */
285 xi->current_csum_supported = FALSE;
286 xi->current_gso_value = 0;
287 xi->config_max_pkt_size = xi->current_mtu_value + XN_HDR_SIZE;
288 #else
289 xi->current_csum_supported = xi->frontend_csum_supported && xi->backend_csum_supported;
290 xi->current_gso_value = min(xi->backend_gso_value, xi->backend_gso_value);
291 xi->config_max_pkt_size = max(xi->current_mtu_value + XN_HDR_SIZE, xi->current_gso_value + XN_HDR_SIZE);
292 #endif
294 #if NTDDI_VERSION < NTDDI_VISTA
295 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE)xi, 0, 0 /* the last zero is to give the next | something to | with */
296 #ifdef NDIS51_MINIPORT
297 |NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
298 #endif
299 |NDIS_ATTRIBUTE_DESERIALIZE
300 |NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK,
301 NdisInterfaceInternal); /* PnpBus option doesn't exist... */
302 #else
303 registration_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
304 registration_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
305 registration_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
306 registration_attributes.MiniportAdapterContext = xi;
307 registration_attributes.AttributeFlags = 0;
308 registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE;
309 registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK;
310 registration_attributes.CheckForHangTimeInSeconds = 0; /* use default */
311 registration_attributes.InterfaceType = NdisInterfacePNPBus;
312 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registration_attributes);
313 if (!NT_SUCCESS(status)) {
314 FUNCTION_MSG("NdisMSetMiniportAttributes(registration) failed (%08x)\n", status);
315 goto err;
316 }
318 general_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
319 general_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; /* revision 2 is NDIS 6.2 */
320 general_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
321 general_attributes.Flags = 0;
322 general_attributes.MediaType = NdisMedium802_3;
323 general_attributes.PhysicalMediumType = NdisPhysicalMediumOther;
324 general_attributes.MtuSize = xi->current_mtu_value;
325 general_attributes.MaxXmitLinkSpeed = MAX_LINK_SPEED;
326 general_attributes.XmitLinkSpeed = MAX_LINK_SPEED;
327 general_attributes.MaxRcvLinkSpeed = MAX_LINK_SPEED;
328 general_attributes.RcvLinkSpeed = MAX_LINK_SPEED;
329 general_attributes.MediaConnectState = MediaConnectStateConnected;
330 general_attributes.MediaDuplexState = MediaDuplexStateFull;
331 general_attributes.LookaheadSize = xi->current_lookahead;
332 general_attributes.PowerManagementCapabilities = NULL;
333 general_attributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
334 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
335 NDIS_MAC_OPTION_NO_LOOPBACK;
336 general_attributes.SupportedPacketFilters = SUPPORTED_PACKET_FILTERS;
337 general_attributes.MaxMulticastListSize = MULTICAST_LIST_MAX_SIZE;
338 general_attributes.MacAddressLength = 6;
339 NdisMoveMemory(general_attributes.PermanentMacAddress, xi->perm_mac_addr, general_attributes.MacAddressLength);
340 NdisMoveMemory(general_attributes.CurrentMacAddress, xi->curr_mac_addr, general_attributes.MacAddressLength);
341 general_attributes.RecvScaleCapabilities = NULL; /* we do want to support this soon */
342 general_attributes.AccessType = NET_IF_ACCESS_BROADCAST;
343 general_attributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
344 general_attributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;
345 general_attributes.IfType = IF_TYPE_ETHERNET_CSMACD;
346 general_attributes.IfConnectorPresent = TRUE;
347 general_attributes.SupportedStatistics = xi->stats.SupportedStatistics;
348 general_attributes.SupportedPauseFunctions = NdisPauseFunctionsUnsupported;
349 general_attributes.DataBackFillSize = 0; // see NdisRetreatNetBufferDataStart
350 general_attributes.ContextBackFillSize = 0; // ?? NFI ??
352 for (i = 0; xennet_oids[i].oid; i++);
354 status = NdisAllocateMemoryWithTag((PVOID)&supported_oids, sizeof(NDIS_OID) * i, XENNET_POOL_TAG);
355 if (!NT_SUCCESS(status)) {
356 FUNCTION_MSG("NdisAllocateMemoryWithTag failed with 0x%x\n", status);
357 status = NDIS_STATUS_RESOURCES;
358 goto err;
359 }
361 for (i = 0; xennet_oids[i].oid; i++) {
362 supported_oids[i] = xennet_oids[i].oid;
363 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);
364 }
365 general_attributes.SupportedOidList = supported_oids;
366 general_attributes.SupportedOidListLength = sizeof(NDIS_OID) * i;
367 general_attributes.AutoNegotiationFlags = NDIS_LINK_STATE_XMIT_LINK_SPEED_AUTO_NEGOTIATED
368 | NDIS_LINK_STATE_RCV_LINK_SPEED_AUTO_NEGOTIATED
369 | NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;
370 //general_attributes.PowerManagementCapabilitiesEx = NULL; // >= 6.20
371 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&general_attributes);
372 if (!NT_SUCCESS(status)) {
373 FUNCTION_MSG("NdisMSetMiniportAttributes(general) failed (%08x)\n", status);
374 goto err;
375 }
376 NdisFreeMemory(supported_oids, 0, 0);
378 /* this is the initial offload state */
379 RtlZeroMemory(&df_offload, sizeof(df_offload));
380 df_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
381 df_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
382 df_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
383 /* this is the supported offload state */
384 RtlZeroMemory(&hw_offload, sizeof(hw_offload));
385 hw_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
386 hw_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
387 hw_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
388 if (xi->current_csum_supported)
389 {
390 df_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
391 df_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
392 df_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
393 df_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SET_ON;
394 df_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SET_ON;
395 df_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SET_ON;
396 df_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
397 df_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
398 df_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
399 df_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SET_ON;
400 df_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SET_ON;
401 df_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SET_ON;
402 /* offload.Checksum.IPv6Transmit is not supported */
403 /* offload.Checksum.IPv6Receive is not supported */
404 hw_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
405 hw_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
406 hw_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
407 hw_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
408 hw_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
409 hw_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
410 hw_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
411 hw_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
412 hw_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
413 hw_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
414 hw_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
415 hw_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
416 /* hw_offload.Checksum.IPv6Transmit is not supported */
417 /* hw_offload.Checksum.IPv6Receive is not supported */
418 }
419 if (xi->current_gso_value)
420 {
421 hw_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
422 hw_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
423 hw_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
424 hw_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
425 hw_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
426 hw_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
427 hw_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
428 hw_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
429 /* hw_offload.LsoV2.IPv6 is not supported */
430 df_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
431 df_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
432 df_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
433 df_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
434 df_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
435 df_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
436 df_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
437 df_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
438 /* df_offload.LsoV2.IPv6 is not supported */
439 }
440 /* hw_offload.IPsecV1 is not supported */
441 /* hw_offload.IPsecV2 is not supported */
442 /* df_offload.IPsecV1 is not supported */
443 /* df_offload.IPsecV2 is not supported */
444 hw_offload.Flags = 0;
445 df_offload.Flags = 0;
447 RtlZeroMemory(&df_conn_offload, sizeof(df_conn_offload));
448 df_conn_offload.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
449 df_conn_offload.Header.Revision = NDIS_TCP_CONNECTION_OFFLOAD_REVISION_1;
450 df_conn_offload.Header.Size = NDIS_SIZEOF_TCP_CONNECTION_OFFLOAD_REVISION_1;
452 RtlZeroMemory(&hw_conn_offload, sizeof(hw_conn_offload));
453 hw_conn_offload.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
454 hw_conn_offload.Header.Revision = NDIS_TCP_CONNECTION_OFFLOAD_REVISION_1;
455 hw_conn_offload.Header.Size = NDIS_SIZEOF_TCP_CONNECTION_OFFLOAD_REVISION_1;
457 offload_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
458 offload_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
459 offload_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
460 offload_attributes.DefaultOffloadConfiguration = &df_offload;
461 offload_attributes.HardwareOffloadCapabilities = &hw_offload;
462 offload_attributes.DefaultTcpConnectionOffloadConfiguration = &df_conn_offload;
463 offload_attributes.TcpConnectionOffloadHardwareCapabilities = &hw_conn_offload;
464 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offload_attributes);
465 if (!NT_SUCCESS(status)) {
466 FUNCTION_MSG("NdisMSetMiniportAttributes(offload) failed (%08x)\n", status);
467 goto err;
468 }
470 #if 0
471 if (ndis_os_minor_version >= 1) {
472 NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES hw_assist_attributes;
473 NDIS_HD_SPLIT_ATTRIBUTES hd_split_attributes;
475 RtlZeroMemory(&hd_split_attributes, sizeof(hd_split_attributes));
476 hd_split_attributes.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;
477 hd_split_attributes.Header.Revision = NDIS_HD_SPLIT_ATTRIBUTES_REVISION_1;
478 hd_split_attributes.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;
479 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;
480 hd_split_attributes.CurrentCapabilities = hd_split_attributes.HardwareCapabilities;
481 /* the other members are set on output */
483 RtlZeroMemory(&hw_assist_attributes, sizeof(hw_assist_attributes));
484 hw_assist_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;
485 hw_assist_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
486 hw_assist_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
487 hw_assist_attributes.HDSplitAttributes = &hd_split_attributes;
488 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&hw_assist_attributes);
489 if (!NT_SUCCESS(status))
490 {
491 FUNCTION_MSG("NdisMSetMiniportAttributes(hw_assist) failed (%08x)\n", status);
492 goto err;
493 }
494 FUNCTION_MSG("HW Split enabled\n");
495 FUNCTION_MSG(" HDSplitFlags = %08x\n", hd_split_attributes.HDSplitFlags);
496 FUNCTION_MSG(" BackfillSize = %d\n", hd_split_attributes.BackfillSize);
497 FUNCTION_MSG(" MaxHeaderSize = %d\n", hd_split_attributes.MaxHeaderSize);
498 //what about backfill here?
499 }
500 #endif
501 #endif
502 if (xi->device_state != DEVICE_STATE_INACTIVE)
503 xi->device_state = DEVICE_STATE_ACTIVE;
504 FUNCTION_EXIT();
505 return NDIS_STATUS_SUCCESS;
507 err:
508 if (xi) {
509 NdisFreeMemory(xi, 0, 0);
510 }
511 FUNCTION_EXIT_STATUS(status);
513 return status;
514 }
516 #if NTDDI_VERSION < NTDDI_VISTA
517 static VOID
518 XenNet_PnPEventNotify(NDIS_HANDLE adapter_context, NDIS_DEVICE_PNP_EVENT pnp_event, PVOID information_buffer, ULONG information_buffer_length) {
519 UNREFERENCED_PARAMETER(information_buffer);
520 UNREFERENCED_PARAMETER(information_buffer_length);
521 UNREFERENCED_PARAMETER(adapter_context);
523 FUNCTION_ENTER();
524 switch (pnp_event)
525 {
526 case NdisDevicePnPEventSurpriseRemoved:
527 FUNCTION_MSG("NdisDevicePnPEventSurpriseRemoved\n");
528 break;
529 case NdisDevicePnPEventPowerProfileChanged :
530 FUNCTION_MSG("NdisDevicePnPEventPowerProfileChanged\n");
531 break;
532 default:
533 FUNCTION_MSG("NdisDevicePnPEvent%d\n", pnp_event);
534 break;
535 }
536 FUNCTION_EXIT();
537 }
538 #else
539 static VOID
540 XenNet_DevicePnPEventNotify(NDIS_HANDLE adapter_context, PNET_DEVICE_PNP_EVENT pnp_event) {
541 UNREFERENCED_PARAMETER(adapter_context);
543 FUNCTION_ENTER();
544 switch (pnp_event->DevicePnPEvent)
545 {
546 case NdisDevicePnPEventSurpriseRemoved:
547 FUNCTION_MSG("NdisDevicePnPEventSurpriseRemoved\n");
548 break;
549 case NdisDevicePnPEventPowerProfileChanged :
550 FUNCTION_MSG("NdisDevicePnPEventPowerProfileChanged\n");
551 break;
552 default:
553 FUNCTION_MSG("NdisDevicePnPEvent%d\n", pnp_event->DevicePnPEvent);
554 break;
555 }
556 FUNCTION_EXIT();
557 }
558 #endif
560 /* called at <= HIGH_IRQL, or PASSIVE_LEVEL, depending on shutdown_action */
561 static VOID
562 #if NTDDI_VERSION < NTDDI_VISTA
563 XenNet_Shutdown(NDIS_HANDLE adapter_context) {
564 #else
565 XenNet_Shutdown(NDIS_HANDLE adapter_context, NDIS_SHUTDOWN_ACTION shutdown_action) {
566 UNREFERENCED_PARAMETER(shutdown_action);
567 #endif
568 UNREFERENCED_PARAMETER(adapter_context);
569 FUNCTION_ENTER();
570 FUNCTION_EXIT();
571 }
573 static BOOLEAN
574 XenNet_CheckForHang(NDIS_HANDLE adapter_context)
575 {
576 UNREFERENCED_PARAMETER(adapter_context);
578 //FUNCTION_ENTER();
579 //FUNCTION_EXIT();
580 return FALSE;
581 }
583 /* Opposite of XenNet_Init */
584 static VOID
585 #if NTDDI_VERSION < NTDDI_VISTA
586 XenNet_Halt(NDIS_HANDLE adapter_context) {
587 #else
588 XenNet_Halt(NDIS_HANDLE adapter_context, NDIS_HALT_ACTION halt_action) {
589 #endif
590 struct xennet_info *xi = adapter_context;
591 #if NTDDI_VERSION < NTDDI_VISTA
592 #else
593 UNREFERENCED_PARAMETER(halt_action);
594 #endif
595 FUNCTION_ENTER();
596 XenNet_Disconnect(xi, FALSE);
597 NdisFreeMemory(xi, 0, 0);
599 FUNCTION_EXIT();
600 }
602 static NDIS_STATUS
603 XenNet_Reset(NDIS_HANDLE adapter_context, PBOOLEAN addressing_reset)
604 {
605 UNREFERENCED_PARAMETER(adapter_context);
607 FUNCTION_ENTER();
608 *addressing_reset = FALSE;
609 FUNCTION_EXIT();
610 return NDIS_STATUS_SUCCESS;
611 }
613 #if NTDDI_VERSION < NTDDI_VISTA
614 #else
615 /* called at PASSIVE_LEVEL */
616 static NDIS_STATUS
617 XenNet_Pause(NDIS_HANDLE adapter_context, PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters)
618 {
619 UNREFERENCED_PARAMETER(adapter_context);
620 UNREFERENCED_PARAMETER(pause_parameters);
621 FUNCTION_ENTER();
622 FUNCTION_EXIT();
623 return STATUS_SUCCESS;
624 }
626 /* called at PASSIVE_LEVEL */
627 static NDIS_STATUS
628 XenNet_Restart(NDIS_HANDLE adapter_context, PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters)
629 {
630 UNREFERENCED_PARAMETER(adapter_context);
631 UNREFERENCED_PARAMETER(restart_parameters);
632 FUNCTION_ENTER();
633 FUNCTION_EXIT();
634 return STATUS_SUCCESS;
635 }
637 static VOID
638 XenNet_Unload(PDRIVER_OBJECT driver_object)
639 {
640 UNREFERENCED_PARAMETER(driver_object);
641 FUNCTION_ENTER();
642 NdisMDeregisterMiniportDriver(driver_handle);
643 FUNCTION_EXIT();
644 }
646 static NDIS_STATUS
647 XenNet_SetOptions(NDIS_HANDLE driver_handle, NDIS_HANDLE driver_context)
648 {
649 UNREFERENCED_PARAMETER(driver_handle);
650 UNREFERENCED_PARAMETER(driver_context);
651 FUNCTION_ENTER();
652 FUNCTION_EXIT();
653 return STATUS_SUCCESS;
654 }
655 #endif
657 NTSTATUS
658 DriverEntry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path)
659 {
660 NTSTATUS status;
661 ULONG ndis_version;
662 #if NTDDI_VERSION < NTDDI_VISTA
663 NDIS_HANDLE ndis_wrapper_handle = NULL;
664 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
665 #else
666 NDIS_MINIPORT_DRIVER_CHARACTERISTICS mini_chars;
667 #endif
669 FUNCTION_ENTER();
671 NdisZeroMemory(&mini_chars, sizeof(mini_chars));
673 ndis_version = NdisGetVersion();
675 ndis_os_major_version = (USHORT)(ndis_version >> 16);
676 ndis_os_minor_version = (USHORT)(ndis_version & 0xFFFF);
678 FUNCTION_MSG("Driver MajorNdisVersion = %d, Driver MinorNdisVersion = %d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION);
679 FUNCTION_MSG("Windows MajorNdisVersion = %d, Windows MinorNdisVersion = %d\n", ndis_os_major_version, ndis_os_minor_version);
681 #if NTDDI_VERSION < NTDDI_VISTA
682 NdisMInitializeWrapper(&ndis_wrapper_handle, driver_object, registry_path, NULL);
683 if (!ndis_wrapper_handle) {
684 FUNCTION_MSG("NdisMInitializeWrapper failed\n");
685 return NDIS_STATUS_FAILURE;
686 }
688 mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
689 mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
690 mini_chars.HaltHandler = XenNet_Halt;
691 mini_chars.InitializeHandler = XenNet_Init;
692 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
693 mini_chars.ResetHandler = XenNet_Reset;
694 mini_chars.SetInformationHandler = XenNet_SetInformation;
695 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
696 mini_chars.SendPacketsHandler = XenNet_SendPackets;
697 #ifdef NDIS51_MINIPORT
698 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
699 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
700 #endif
701 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
702 if (!NT_SUCCESS(status)) {
703 FUNCTION_MSG("NdisMRegisterMiniport failed, status = 0x%x\n", status);
704 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
705 return status;
706 }
707 #else
708 mini_chars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
710 if (ndis_os_minor_version < 1) {
711 mini_chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
712 mini_chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
714 mini_chars.MajorNdisVersion = 6;
715 mini_chars.MinorNdisVersion = 0;
716 } else {
717 mini_chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
718 mini_chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
719 mini_chars.MajorNdisVersion = 6;
720 mini_chars.MinorNdisVersion = 1;
721 }
722 mini_chars.MajorDriverVersion = VENDOR_DRIVER_VERSION_MAJOR;
723 mini_chars.MinorDriverVersion = VENDOR_DRIVER_VERSION_MINOR;
725 mini_chars.Flags = NDIS_WDM_DRIVER;
727 mini_chars.SetOptionsHandler = XenNet_SetOptions;
728 mini_chars.InitializeHandlerEx = XenNet_Initialize;
729 mini_chars.HaltHandlerEx = XenNet_Halt;
730 mini_chars.UnloadHandler = XenNet_Unload;
731 mini_chars.PauseHandler = XenNet_Pause;
732 mini_chars.RestartHandler = XenNet_Restart;
733 mini_chars.CheckForHangHandlerEx = XenNet_CheckForHang;
734 mini_chars.ResetHandlerEx = XenNet_Reset;
735 mini_chars.DevicePnPEventNotifyHandler = XenNet_DevicePnPEventNotify;
736 mini_chars.ShutdownHandlerEx = XenNet_Shutdown;
738 mini_chars.OidRequestHandler = XenNet_OidRequest;
739 mini_chars.CancelOidRequestHandler = XenNet_CancelOidRequest;
740 if (ndis_os_minor_version >= 1) {
741 mini_chars.DirectOidRequestHandler = NULL;
742 mini_chars.CancelDirectOidRequestHandler = NULL;
743 }
745 mini_chars.SendNetBufferListsHandler = XenNet_SendNetBufferLists;
746 mini_chars.CancelSendHandler = XenNet_CancelSend;
748 mini_chars.ReturnNetBufferListsHandler = XenNet_ReturnNetBufferLists;
750 status = NdisMRegisterMiniportDriver(driver_object, registry_path, NULL, &mini_chars, &driver_handle);
751 if (!NT_SUCCESS(status)) {
752 FUNCTION_MSG("NdisMRegisterMiniportDriver failed, status = 0x%x\n", status);
753 return status;
754 }
755 #endif
756 FUNCTION_EXIT();
758 return status;
759 }