win-pvdrivers

view xennet/xennet.c @ 1045:f6a7b0654b9c

Added tag 0.11.0.399 for changeset 9f476ac2fbe1
author James Harper <james.harper@bendigoit.com.au>
date Mon Mar 04 14:36:18 2013 +1100 (2013-03-04)
parents 43e76afb2398
children 5bb1f345e06a
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_DFL_MIN_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 XenNet_Connect(xi, FALSE);
273 if (!xi->backend_sg_supported)
274 xi->backend_gso_value = min(xi->backend_gso_value, PAGE_SIZE - MAX_PKT_HEADER_LENGTH);
276 xi->current_sg_supported = xi->frontend_sg_supported && xi->backend_sg_supported;
277 xi->current_mtu_value = xi->frontend_mtu_value;
278 xi->current_gso_rx_split_type = xi->frontend_gso_rx_split_type;
280 #if NTDDI_VERSION < NTDDI_VISTA
281 /* these are set by OID for NDIS5 */
282 xi->current_csum_supported = FALSE;
283 xi->current_gso_value = 0;
284 xi->config_max_pkt_size = xi->current_mtu_value + XN_HDR_SIZE;
285 #else
286 xi->current_csum_supported = xi->frontend_csum_supported && xi->backend_csum_supported;
287 xi->current_gso_value = min(xi->backend_gso_value, xi->backend_gso_value);
288 xi->config_max_pkt_size = max(xi->current_mtu_value + XN_HDR_SIZE, xi->current_gso_value + XN_HDR_SIZE);
289 #endif
291 #if NTDDI_VERSION < NTDDI_VISTA
292 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE)xi, 0, 0 /* the last zero is to give the next | something to | with */
293 #ifdef NDIS51_MINIPORT
294 |NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
295 #endif
296 |NDIS_ATTRIBUTE_DESERIALIZE
297 |NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK,
298 NdisInterfaceInternal); /* PnpBus option doesn't exist... */
299 #else
300 registration_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
301 registration_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
302 registration_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
303 registration_attributes.MiniportAdapterContext = xi;
304 registration_attributes.AttributeFlags = 0;
305 registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE;
306 registration_attributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK;
307 registration_attributes.CheckForHangTimeInSeconds = 0; /* use default */
308 registration_attributes.InterfaceType = NdisInterfacePNPBus;
309 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registration_attributes);
310 if (!NT_SUCCESS(status)) {
311 FUNCTION_MSG("NdisMSetMiniportAttributes(registration) failed (%08x)\n", status);
312 goto err;
313 }
315 general_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
316 general_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; /* revision 2 is NDIS 6.2 */
317 general_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
318 general_attributes.Flags = 0;
319 general_attributes.MediaType = NdisMedium802_3;
320 general_attributes.PhysicalMediumType = NdisPhysicalMediumOther;
321 general_attributes.MtuSize = xi->current_mtu_value;
322 general_attributes.MaxXmitLinkSpeed = MAX_LINK_SPEED;
323 general_attributes.XmitLinkSpeed = MAX_LINK_SPEED;
324 general_attributes.MaxRcvLinkSpeed = MAX_LINK_SPEED;
325 general_attributes.RcvLinkSpeed = MAX_LINK_SPEED;
326 general_attributes.MediaConnectState = MediaConnectStateConnected;
327 general_attributes.MediaDuplexState = MediaDuplexStateFull;
328 general_attributes.LookaheadSize = xi->current_lookahead;
329 general_attributes.PowerManagementCapabilities = NULL;
330 general_attributes.MacOptions = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
331 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
332 NDIS_MAC_OPTION_NO_LOOPBACK;
333 general_attributes.SupportedPacketFilters = SUPPORTED_PACKET_FILTERS;
334 general_attributes.MaxMulticastListSize = MULTICAST_LIST_MAX_SIZE;
335 general_attributes.MacAddressLength = 6;
336 NdisMoveMemory(general_attributes.PermanentMacAddress, xi->perm_mac_addr, general_attributes.MacAddressLength);
337 NdisMoveMemory(general_attributes.CurrentMacAddress, xi->curr_mac_addr, general_attributes.MacAddressLength);
338 general_attributes.RecvScaleCapabilities = NULL; /* we do want to support this soon */
339 general_attributes.AccessType = NET_IF_ACCESS_BROADCAST;
340 general_attributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
341 general_attributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;
342 general_attributes.IfType = IF_TYPE_ETHERNET_CSMACD;
343 general_attributes.IfConnectorPresent = TRUE;
344 general_attributes.SupportedStatistics = xi->stats.SupportedStatistics;
345 general_attributes.SupportedPauseFunctions = NdisPauseFunctionsUnsupported;
346 general_attributes.DataBackFillSize = 0; // see NdisRetreatNetBufferDataStart
347 general_attributes.ContextBackFillSize = 0; // ?? NFI ??
349 for (i = 0; xennet_oids[i].oid; i++);
351 status = NdisAllocateMemoryWithTag((PVOID)&supported_oids, sizeof(NDIS_OID) * i, XENNET_POOL_TAG);
352 if (!NT_SUCCESS(status)) {
353 FUNCTION_MSG("NdisAllocateMemoryWithTag failed with 0x%x\n", status);
354 status = NDIS_STATUS_RESOURCES;
355 goto err;
356 }
358 for (i = 0; xennet_oids[i].oid; i++) {
359 supported_oids[i] = xennet_oids[i].oid;
360 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);
361 }
362 general_attributes.SupportedOidList = supported_oids;
363 general_attributes.SupportedOidListLength = sizeof(NDIS_OID) * i;
364 general_attributes.AutoNegotiationFlags = NDIS_LINK_STATE_XMIT_LINK_SPEED_AUTO_NEGOTIATED
365 | NDIS_LINK_STATE_RCV_LINK_SPEED_AUTO_NEGOTIATED
366 | NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;
367 //general_attributes.PowerManagementCapabilitiesEx = NULL; // >= 6.20
368 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&general_attributes);
369 if (!NT_SUCCESS(status)) {
370 FUNCTION_MSG("NdisMSetMiniportAttributes(general) failed (%08x)\n", status);
371 goto err;
372 }
373 NdisFreeMemory(supported_oids, 0, 0);
375 /* this is the initial offload state */
376 RtlZeroMemory(&df_offload, sizeof(df_offload));
377 df_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
378 df_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
379 df_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
380 /* this is the supported offload state */
381 RtlZeroMemory(&hw_offload, sizeof(hw_offload));
382 hw_offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
383 hw_offload.Header.Revision = NDIS_OFFLOAD_REVISION_1; // revision 2 does exist
384 hw_offload.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1;
385 if (xi->current_csum_supported)
386 {
387 df_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
388 df_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
389 df_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
390 df_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SET_ON;
391 df_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SET_ON;
392 df_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SET_ON;
393 df_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
394 df_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SET_ON;
395 df_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SET_ON;
396 df_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SET_ON;
397 df_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SET_ON;
398 df_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SET_ON;
399 /* offload.Checksum.IPv6Transmit is not supported */
400 /* offload.Checksum.IPv6Receive is not supported */
401 hw_offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
402 hw_offload.Checksum.IPv4Transmit.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
403 hw_offload.Checksum.IPv4Transmit.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
404 hw_offload.Checksum.IPv4Transmit.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
405 hw_offload.Checksum.IPv4Transmit.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
406 hw_offload.Checksum.IPv4Transmit.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
407 hw_offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
408 hw_offload.Checksum.IPv4Receive.IpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
409 hw_offload.Checksum.IPv4Receive.TcpOptionsSupported = NDIS_OFFLOAD_SUPPORTED;
410 hw_offload.Checksum.IPv4Receive.TcpChecksum = NDIS_OFFLOAD_SUPPORTED;
411 hw_offload.Checksum.IPv4Receive.UdpChecksum = NDIS_OFFLOAD_SUPPORTED;
412 hw_offload.Checksum.IPv4Receive.IpChecksum = NDIS_OFFLOAD_SUPPORTED;
413 /* hw_offload.Checksum.IPv6Transmit is not supported */
414 /* hw_offload.Checksum.IPv6Receive is not supported */
415 }
416 if (xi->current_gso_value)
417 {
418 hw_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
419 hw_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
420 hw_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
421 hw_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
422 hw_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
423 hw_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
424 hw_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
425 hw_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
426 /* hw_offload.LsoV2.IPv6 is not supported */
427 df_offload.LsoV1.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
428 df_offload.LsoV1.IPv4.MaxOffLoadSize = xi->current_gso_value;
429 df_offload.LsoV1.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
430 df_offload.LsoV1.IPv4.TcpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
431 df_offload.LsoV1.IPv4.IpOptions = NDIS_OFFLOAD_NOT_SUPPORTED; /* linux can't handle this */
432 df_offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
433 df_offload.LsoV2.IPv4.MaxOffLoadSize = xi->current_gso_value;
434 df_offload.LsoV2.IPv4.MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
435 /* df_offload.LsoV2.IPv6 is not supported */
436 }
437 /* hw_offload.IPsecV1 is not supported */
438 /* hw_offload.IPsecV2 is not supported */
439 /* df_offload.IPsecV1 is not supported */
440 /* df_offload.IPsecV2 is not supported */
441 hw_offload.Flags = 0;
442 df_offload.Flags = 0;
444 RtlZeroMemory(&df_conn_offload, sizeof(df_conn_offload));
445 df_conn_offload.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
446 df_conn_offload.Header.Revision = NDIS_TCP_CONNECTION_OFFLOAD_REVISION_1;
447 df_conn_offload.Header.Size = NDIS_SIZEOF_TCP_CONNECTION_OFFLOAD_REVISION_1;
449 RtlZeroMemory(&hw_conn_offload, sizeof(hw_conn_offload));
450 hw_conn_offload.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
451 hw_conn_offload.Header.Revision = NDIS_TCP_CONNECTION_OFFLOAD_REVISION_1;
452 hw_conn_offload.Header.Size = NDIS_SIZEOF_TCP_CONNECTION_OFFLOAD_REVISION_1;
454 offload_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
455 offload_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
456 offload_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
457 offload_attributes.DefaultOffloadConfiguration = &df_offload;
458 offload_attributes.HardwareOffloadCapabilities = &hw_offload;
459 offload_attributes.DefaultTcpConnectionOffloadConfiguration = &df_conn_offload;
460 offload_attributes.TcpConnectionOffloadHardwareCapabilities = &hw_conn_offload;
461 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offload_attributes);
462 if (!NT_SUCCESS(status)) {
463 FUNCTION_MSG("NdisMSetMiniportAttributes(offload) failed (%08x)\n", status);
464 goto err;
465 }
467 #if 0
468 if (ndis_os_minor_version >= 1) {
469 NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES hw_assist_attributes;
470 NDIS_HD_SPLIT_ATTRIBUTES hd_split_attributes;
472 RtlZeroMemory(&hd_split_attributes, sizeof(hd_split_attributes));
473 hd_split_attributes.Header.Type = NDIS_OBJECT_TYPE_HD_SPLIT_ATTRIBUTES;
474 hd_split_attributes.Header.Revision = NDIS_HD_SPLIT_ATTRIBUTES_REVISION_1;
475 hd_split_attributes.Header.Size = NDIS_SIZEOF_HD_SPLIT_ATTRIBUTES_REVISION_1;
476 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;
477 hd_split_attributes.CurrentCapabilities = hd_split_attributes.HardwareCapabilities;
478 /* the other members are set on output */
480 RtlZeroMemory(&hw_assist_attributes, sizeof(hw_assist_attributes));
481 hw_assist_attributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES;
482 hw_assist_attributes.Header.Revision = NDIS_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
483 hw_assist_attributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_HARDWARE_ASSIST_ATTRIBUTES_REVISION_1;
484 hw_assist_attributes.HDSplitAttributes = &hd_split_attributes;
485 status = NdisMSetMiniportAttributes(xi->adapter_handle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&hw_assist_attributes);
486 if (!NT_SUCCESS(status))
487 {
488 FUNCTION_MSG("NdisMSetMiniportAttributes(hw_assist) failed (%08x)\n", status);
489 goto err;
490 }
491 FUNCTION_MSG("HW Split enabled\n");
492 FUNCTION_MSG(" HDSplitFlags = %08x\n", hd_split_attributes.HDSplitFlags);
493 FUNCTION_MSG(" BackfillSize = %d\n", hd_split_attributes.BackfillSize);
494 FUNCTION_MSG(" MaxHeaderSize = %d\n", hd_split_attributes.MaxHeaderSize);
495 //what about backfill here?
496 }
497 #endif
498 #endif
499 if (xi->device_state != DEVICE_STATE_INACTIVE)
500 xi->device_state = DEVICE_STATE_ACTIVE;
501 FUNCTION_EXIT();
502 return NDIS_STATUS_SUCCESS;
504 err:
505 if (xi) {
506 NdisFreeMemory(xi, 0, 0);
507 }
508 FUNCTION_EXIT_STATUS(status);
510 return status;
511 }
513 #if NTDDI_VERSION < NTDDI_VISTA
514 static VOID
515 XenNet_PnPEventNotify(NDIS_HANDLE adapter_context, NDIS_DEVICE_PNP_EVENT pnp_event, PVOID information_buffer, ULONG information_buffer_length) {
516 UNREFERENCED_PARAMETER(information_buffer);
517 UNREFERENCED_PARAMETER(information_buffer_length);
518 UNREFERENCED_PARAMETER(adapter_context);
520 FUNCTION_ENTER();
521 switch (pnp_event)
522 {
523 case NdisDevicePnPEventSurpriseRemoved:
524 FUNCTION_MSG("NdisDevicePnPEventSurpriseRemoved\n");
525 break;
526 case NdisDevicePnPEventPowerProfileChanged :
527 FUNCTION_MSG("NdisDevicePnPEventPowerProfileChanged\n");
528 break;
529 default:
530 FUNCTION_MSG("NdisDevicePnPEvent%d\n", pnp_event);
531 break;
532 }
533 FUNCTION_EXIT();
534 }
535 #else
536 static VOID
537 XenNet_DevicePnPEventNotify(NDIS_HANDLE adapter_context, PNET_DEVICE_PNP_EVENT pnp_event) {
538 UNREFERENCED_PARAMETER(adapter_context);
540 FUNCTION_ENTER();
541 switch (pnp_event->DevicePnPEvent)
542 {
543 case NdisDevicePnPEventSurpriseRemoved:
544 FUNCTION_MSG("NdisDevicePnPEventSurpriseRemoved\n");
545 break;
546 case NdisDevicePnPEventPowerProfileChanged :
547 FUNCTION_MSG("NdisDevicePnPEventPowerProfileChanged\n");
548 break;
549 default:
550 FUNCTION_MSG("NdisDevicePnPEvent%d\n", pnp_event->DevicePnPEvent);
551 break;
552 }
553 FUNCTION_EXIT();
554 }
555 #endif
557 /* called at <= HIGH_IRQL, or PASSIVE_LEVEL, depending on shutdown_action */
558 static VOID
559 #if NTDDI_VERSION < NTDDI_VISTA
560 XenNet_Shutdown(NDIS_HANDLE adapter_context) {
561 #else
562 XenNet_Shutdown(NDIS_HANDLE adapter_context, NDIS_SHUTDOWN_ACTION shutdown_action) {
563 UNREFERENCED_PARAMETER(shutdown_action);
564 #endif
565 UNREFERENCED_PARAMETER(adapter_context);
566 FUNCTION_ENTER();
567 FUNCTION_EXIT();
568 }
570 static BOOLEAN
571 XenNet_CheckForHang(NDIS_HANDLE adapter_context)
572 {
573 UNREFERENCED_PARAMETER(adapter_context);
575 //FUNCTION_ENTER();
576 //FUNCTION_EXIT();
577 return FALSE;
578 }
580 /* Opposite of XenNet_Init */
581 static VOID
582 #if NTDDI_VERSION < NTDDI_VISTA
583 XenNet_Halt(NDIS_HANDLE adapter_context) {
584 #else
585 XenNet_Halt(NDIS_HANDLE adapter_context, NDIS_HALT_ACTION halt_action) {
586 #endif
587 struct xennet_info *xi = adapter_context;
588 #if NTDDI_VERSION < NTDDI_VISTA
589 #else
590 UNREFERENCED_PARAMETER(halt_action);
591 #endif
592 FUNCTION_ENTER();
593 XenNet_Disconnect(xi, FALSE);
594 NdisFreeMemory(xi, 0, 0);
596 FUNCTION_EXIT();
597 }
599 static NDIS_STATUS
600 XenNet_Reset(NDIS_HANDLE adapter_context, PBOOLEAN addressing_reset)
601 {
602 UNREFERENCED_PARAMETER(adapter_context);
604 FUNCTION_ENTER();
605 *addressing_reset = FALSE;
606 FUNCTION_EXIT();
607 return NDIS_STATUS_SUCCESS;
608 }
610 #if NTDDI_VERSION < NTDDI_VISTA
611 #else
612 /* called at PASSIVE_LEVEL */
613 static NDIS_STATUS
614 XenNet_Pause(NDIS_HANDLE adapter_context, PNDIS_MINIPORT_PAUSE_PARAMETERS pause_parameters)
615 {
616 UNREFERENCED_PARAMETER(adapter_context);
617 UNREFERENCED_PARAMETER(pause_parameters);
618 FUNCTION_ENTER();
619 FUNCTION_EXIT();
620 return STATUS_SUCCESS;
621 }
623 /* called at PASSIVE_LEVEL */
624 static NDIS_STATUS
625 XenNet_Restart(NDIS_HANDLE adapter_context, PNDIS_MINIPORT_RESTART_PARAMETERS restart_parameters)
626 {
627 UNREFERENCED_PARAMETER(adapter_context);
628 UNREFERENCED_PARAMETER(restart_parameters);
629 FUNCTION_ENTER();
630 FUNCTION_EXIT();
631 return STATUS_SUCCESS;
632 }
634 static VOID
635 XenNet_Unload(PDRIVER_OBJECT driver_object)
636 {
637 UNREFERENCED_PARAMETER(driver_object);
638 FUNCTION_ENTER();
639 NdisMDeregisterMiniportDriver(driver_handle);
640 FUNCTION_EXIT();
641 }
643 static NDIS_STATUS
644 XenNet_SetOptions(NDIS_HANDLE driver_handle, NDIS_HANDLE driver_context)
645 {
646 UNREFERENCED_PARAMETER(driver_handle);
647 UNREFERENCED_PARAMETER(driver_context);
648 FUNCTION_ENTER();
649 FUNCTION_EXIT();
650 return STATUS_SUCCESS;
651 }
652 #endif
654 NTSTATUS
655 DriverEntry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path)
656 {
657 NTSTATUS status;
658 ULONG ndis_version;
659 #if NTDDI_VERSION < NTDDI_VISTA
660 NDIS_HANDLE ndis_wrapper_handle = NULL;
661 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
662 #else
663 NDIS_MINIPORT_DRIVER_CHARACTERISTICS mini_chars;
664 #endif
666 FUNCTION_ENTER();
668 NdisZeroMemory(&mini_chars, sizeof(mini_chars));
670 ndis_version = NdisGetVersion();
672 ndis_os_major_version = (USHORT)(ndis_version >> 16);
673 ndis_os_minor_version = (USHORT)(ndis_version & 0xFFFF);
675 FUNCTION_MSG("Driver MajorNdisVersion = %d, Driver MinorNdisVersion = %d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION);
676 FUNCTION_MSG("Windows MajorNdisVersion = %d, Windows MinorNdisVersion = %d\n", ndis_os_major_version, ndis_os_minor_version);
678 #if NTDDI_VERSION < NTDDI_VISTA
679 NdisMInitializeWrapper(&ndis_wrapper_handle, driver_object, registry_path, NULL);
680 if (!ndis_wrapper_handle) {
681 FUNCTION_MSG("NdisMInitializeWrapper failed\n");
682 return NDIS_STATUS_FAILURE;
683 }
685 mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
686 mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
687 mini_chars.HaltHandler = XenNet_Halt;
688 mini_chars.InitializeHandler = XenNet_Init;
689 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
690 mini_chars.ResetHandler = XenNet_Reset;
691 mini_chars.SetInformationHandler = XenNet_SetInformation;
692 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
693 mini_chars.SendPacketsHandler = XenNet_SendPackets;
694 #ifdef NDIS51_MINIPORT
695 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
696 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
697 #endif
698 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
699 if (!NT_SUCCESS(status)) {
700 FUNCTION_MSG("NdisMRegisterMiniport failed, status = 0x%x\n", status);
701 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
702 return status;
703 }
704 #else
705 mini_chars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
707 if (ndis_os_minor_version < 1) {
708 mini_chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
709 mini_chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
711 mini_chars.MajorNdisVersion = 6;
712 mini_chars.MinorNdisVersion = 0;
713 } else {
714 mini_chars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
715 mini_chars.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
716 mini_chars.MajorNdisVersion = 6;
717 mini_chars.MinorNdisVersion = 1;
718 }
719 mini_chars.MajorDriverVersion = VENDOR_DRIVER_VERSION_MAJOR;
720 mini_chars.MinorDriverVersion = VENDOR_DRIVER_VERSION_MINOR;
722 mini_chars.Flags = NDIS_WDM_DRIVER;
724 mini_chars.SetOptionsHandler = XenNet_SetOptions;
725 mini_chars.InitializeHandlerEx = XenNet_Initialize;
726 mini_chars.HaltHandlerEx = XenNet_Halt;
727 mini_chars.UnloadHandler = XenNet_Unload;
728 mini_chars.PauseHandler = XenNet_Pause;
729 mini_chars.RestartHandler = XenNet_Restart;
730 mini_chars.CheckForHangHandlerEx = XenNet_CheckForHang;
731 mini_chars.ResetHandlerEx = XenNet_Reset;
732 mini_chars.DevicePnPEventNotifyHandler = XenNet_DevicePnPEventNotify;
733 mini_chars.ShutdownHandlerEx = XenNet_Shutdown;
735 mini_chars.OidRequestHandler = XenNet_OidRequest;
736 mini_chars.CancelOidRequestHandler = XenNet_CancelOidRequest;
737 if (ndis_os_minor_version >= 1) {
738 mini_chars.DirectOidRequestHandler = NULL;
739 mini_chars.CancelDirectOidRequestHandler = NULL;
740 }
742 mini_chars.SendNetBufferListsHandler = XenNet_SendNetBufferLists;
743 mini_chars.CancelSendHandler = XenNet_CancelSend;
745 mini_chars.ReturnNetBufferListsHandler = XenNet_ReturnNetBufferLists;
747 status = NdisMRegisterMiniportDriver(driver_object, registry_path, NULL, &mini_chars, &driver_handle);
748 if (!NT_SUCCESS(status)) {
749 FUNCTION_MSG("NdisMRegisterMiniportDriver failed, status = 0x%x\n", status);
750 return status;
751 }
752 #endif
753 FUNCTION_EXIT();
755 return status;
756 }