win-pvdrivers

view xennet/xennet_oid.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 c21a4feb4a27
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 "xennet.h"
23 #define DEF_OID_QUERY(oid, min_length) {oid, #oid, min_length, XenNet_Query##oid, NULL}
24 #define DEF_OID_QUERYSET(oid, min_length) {oid, #oid, min_length, XenNet_Query##oid, XenNet_Set##oid}
25 #define DEF_OID_SET(oid, min_length) {oid, #oid, min_length, NULL, XenNet_Set##oid}
26 #define DEF_OID_NONE(oid) {oid, #oid, 0, NULL, NULL} /* define this for a silent but unsupported oid */
28 #define DEF_OID_QUERY_STAT(oid) DEF_OID_QUERY(##oid, 0) /* has to be 0 so the 4/8 size works */
29 #define DEF_OID_QUERY_ULONG(oid) DEF_OID_QUERY(##oid, sizeof(ULONG))
30 #define DEF_OID_QUERYSET_ULONG(oid) DEF_OID_QUERYSET(##oid, sizeof(ULONG))
31 #define DEF_OID_SET_ULONG(oid) DEF_OID_SET(##oid, sizeof(ULONG))
33 #define DEF_OID_QUERY_ROUTINE(oid, value, length) \
34 NDIS_STATUS \
35 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
36 struct xennet_info *xi = context; \
37 UNREFERENCED_PARAMETER(xi); \
38 if (information_buffer_length < length) \
39 { \
40 *bytes_needed = length; \
41 return NDIS_STATUS_BUFFER_TOO_SHORT; \
42 } \
43 *bytes_written = length; \
44 NdisMoveMemory(information_buffer, value, length); \
45 return STATUS_SUCCESS; \
46 }
48 #define DEF_OID_QUERY_ULONG_ROUTINE(oid, value) \
49 NDIS_STATUS \
50 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
51 struct xennet_info *xi = context; \
52 UNREFERENCED_PARAMETER(xi); \
53 UNREFERENCED_PARAMETER(information_buffer_length); \
54 UNREFERENCED_PARAMETER(bytes_needed); \
55 *bytes_written = sizeof(ULONG); \
56 *(ULONG *)information_buffer = value; \
57 return STATUS_SUCCESS; \
58 }
60 #define DEF_OID_QUERY_STAT_ROUTINE(oid, value) \
61 NDIS_STATUS \
62 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
63 struct xennet_info *xi = context; \
64 UNREFERENCED_PARAMETER(xi); \
65 if (information_buffer_length >= sizeof(ULONG64)) \
66 { \
67 *bytes_written = sizeof(ULONG64); \
68 *(ULONG64 *)information_buffer = (value); \
69 } \
70 else if (information_buffer_length >= sizeof(ULONG)) \
71 { \
72 *bytes_written = sizeof(ULONG); \
73 *bytes_needed = sizeof(ULONG64); \
74 *(ULONG *)information_buffer = (ULONG)(value); \
75 } \
76 else \
77 { \
78 *bytes_needed = sizeof(ULONG64); \
79 return NDIS_STATUS_BUFFER_TOO_SHORT; \
80 } \
81 return STATUS_SUCCESS; \
82 }
84 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_TOTAL_SIZE, xi->current_mtu_value + XN_HDR_SIZE)
85 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_PACKET_FILTER, xi->packet_filter)
86 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_LOOKAHEAD, xi->current_lookahead)
87 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BUFFER_SPACE, PAGE_SIZE * NET_TX_RING_SIZE * 4)
88 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BUFFER_SPACE, PAGE_SIZE * NET_RX_RING_SIZE * 2)
89 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BLOCK_SIZE, PAGE_SIZE)
90 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BLOCK_SIZE, PAGE_SIZE)
91 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_SEND_PACKETS, 0)
92 DEF_OID_QUERY_ULONG_ROUTINE(OID_802_3_MAXIMUM_LIST_SIZE, MULTICAST_LIST_MAX_SIZE)
93 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_HARDWARE_STATUS, (xi->device_state == DEVICE_STATE_INACTIVE || xi->device_state == DEVICE_STATE_ACTIVE)?NdisHardwareStatusReady:NdisHardwareStatusInitializing)
94 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_ID, 0xFFFFFF) // Not guaranteed to be XENSOURCE_MAC_HDR;
95 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_DRIVER_VERSION, VENDOR_DRIVER_VERSION)
96 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_SUPPORTED, NdisMedium802_3)
97 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_IN_USE, NdisMedium802_3)
98 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_LOOKAHEAD, MAX_LOOKAHEAD_LENGTH)
100 #if NTDDI_VERSION < NTDDI_VISTA
101 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_FRAME_SIZE, xi->current_mtu_value);
102 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAC_OPTIONS, NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_NO_LOOPBACK);
103 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_CONNECT_STATUS, (xi->device_state == DEVICE_STATE_ACTIVE)?NdisMediaStateConnected:NdisMediaStateDisconnected);
104 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_LINK_SPEED, (ULONG)(MAX_LINK_SPEED / 100));
106 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_OK, xi->stat_tx_ok)
107 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_ERROR, xi->stat_tx_error)
108 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_OK, xi->stat_rx_ok)
109 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_ERROR, xi->stat_rx_error)
110 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_NO_BUFFER, xi->stat_rx_no_buffer)
111 #else
112 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_OK, xi->stats.ifHCOutUcastPkts + xi->stats.ifHCOutMulticastPkts + xi->stats.ifHCOutBroadcastPkts)
113 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_ERROR, xi->stats.ifOutErrors)
114 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_OK, xi->stats.ifHCInUcastPkts + xi->stats.ifHCInMulticastPkts + xi->stats.ifHCInBroadcastPkts)
115 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_ERROR, xi->stats.ifInErrors)
116 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_NO_BUFFER, xi->stats.ifInDiscards)
117 #endif
118 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_RCV_ERROR_ALIGNMENT, 0)
119 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_ONE_COLLISION, 0)
120 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_MORE_COLLISIONS, 0)
122 DEF_OID_QUERY_ROUTINE(OID_GEN_VENDOR_DESCRIPTION, XN_VENDOR_DESC, sizeof(XN_VENDOR_DESC))
124 DEF_OID_QUERY_ROUTINE(OID_802_3_PERMANENT_ADDRESS, xi->perm_mac_addr, ETH_ALEN)
125 DEF_OID_QUERY_ROUTINE(OID_802_3_CURRENT_ADDRESS, xi->curr_mac_addr, ETH_ALEN)
127 DEF_OID_QUERY_ROUTINE(OID_802_3_MULTICAST_LIST, xi->multicast_list, xi->multicast_list_size * 6)
129 NDIS_STATUS
130 XenNet_SetOID_802_3_MULTICAST_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
131 struct xennet_info *xi = context;
132 UCHAR *multicast_list;
133 int i;
134 UNREFERENCED_PARAMETER(bytes_read);
135 UNREFERENCED_PARAMETER(bytes_needed);
137 if (information_buffer_length > MULTICAST_LIST_MAX_SIZE * 6) {
138 return NDIS_STATUS_MULTICAST_FULL;
139 }
141 if (information_buffer_length % 6 != 0) {
142 return NDIS_STATUS_MULTICAST_FULL;
143 }
144 multicast_list = information_buffer;
145 for (i = 0; i < (int)information_buffer_length / 6; i++) {
146 if (!(multicast_list[i * 6 + 0] & 0x01)) {
147 FUNCTION_MSG("Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i,
148 (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1],
149 (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3],
150 (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]);
151 /* the docs say that we should return NDIS_STATUS_MULTICAST_FULL if we get an invalid multicast address but I'm not sure if that's the case... */
152 }
153 }
154 memcpy(xi->multicast_list, multicast_list, information_buffer_length);
155 xi->multicast_list_size = information_buffer_length / 6;
156 return NDIS_STATUS_SUCCESS;
157 }
159 NDIS_STATUS
160 XenNet_SetOID_GEN_CURRENT_PACKET_FILTER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
161 struct xennet_info *xi = context;
162 PULONG data = information_buffer;
164 UNREFERENCED_PARAMETER(information_buffer_length);
165 *bytes_needed = sizeof(ULONG64);
166 if (*data & NDIS_PACKET_TYPE_DIRECTED)
167 FUNCTION_MSG("NDIS_PACKET_TYPE_DIRECTED\n");
168 if (*data & NDIS_PACKET_TYPE_MULTICAST)
169 FUNCTION_MSG("NDIS_PACKET_TYPE_MULTICAST\n");
170 if (*data & NDIS_PACKET_TYPE_ALL_MULTICAST)
171 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_MULTICAST\n");
172 if (*data & NDIS_PACKET_TYPE_BROADCAST)
173 FUNCTION_MSG("NDIS_PACKET_TYPE_BROADCAST\n");
174 if (*data & NDIS_PACKET_TYPE_PROMISCUOUS)
175 FUNCTION_MSG("NDIS_PACKET_TYPE_PROMISCUOUS\n");
176 if (*data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
177 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n");
178 if (*data & NDIS_PACKET_TYPE_ALL_LOCAL)
179 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n");
180 if (*data & NDIS_PACKET_TYPE_FUNCTIONAL)
181 FUNCTION_MSG("NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n");
182 if (*data & NDIS_PACKET_TYPE_GROUP)
183 FUNCTION_MSG("NDIS_PACKET_TYPE_GROUP (not supported)\n");
184 if (*data & ~SUPPORTED_PACKET_FILTERS) {
185 FUNCTION_MSG("returning NDIS_STATUS_NOT_SUPPORTED\n");
186 return NDIS_STATUS_NOT_SUPPORTED;
187 }
188 xi->packet_filter = *(ULONG *)data;
189 *bytes_read = sizeof(ULONG);
190 return NDIS_STATUS_SUCCESS;
191 }
193 NDIS_STATUS
194 XenNet_SetOID_GEN_CURRENT_LOOKAHEAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
195 struct xennet_info *xi = context;
196 PULONG data = information_buffer;
197 UNREFERENCED_PARAMETER(information_buffer_length);
198 UNREFERENCED_PARAMETER(bytes_read);
199 UNREFERENCED_PARAMETER(bytes_needed);
200 xi->current_lookahead = *(ULONG *)data;
201 FUNCTION_MSG("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi);
202 return NDIS_STATUS_SUCCESS;
203 }
205 NDIS_STATUS
206 XenNet_SetOID_GEN_LINK_PARAMETERS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
207 UNREFERENCED_PARAMETER(context);
208 UNREFERENCED_PARAMETER(information_buffer);
209 UNREFERENCED_PARAMETER(information_buffer_length);
210 UNREFERENCED_PARAMETER(bytes_read);
211 UNREFERENCED_PARAMETER(bytes_needed);
212 return STATUS_NOT_SUPPORTED;
213 }
215 #if NTDDI_VERSION < NTDDI_VISTA
216 NDIS_STATUS
217 XenNet_QueryOID_GEN_SUPPORTED_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
218 PNDIS_OID supported_oids;
219 int i;
221 UNREFERENCED_PARAMETER(context);
222 UNREFERENCED_PARAMETER(information_buffer);
223 UNREFERENCED_PARAMETER(information_buffer_length);
224 UNREFERENCED_PARAMETER(bytes_written);
225 UNREFERENCED_PARAMETER(bytes_needed);
227 for (i = 0; xennet_oids[i].oid; i++);
229 if (information_buffer_length < sizeof(NDIS_OID) * i) {
230 *bytes_needed = sizeof(NDIS_OID) * i;
231 return NDIS_STATUS_BUFFER_TOO_SHORT;
232 }
234 supported_oids = information_buffer;
235 for (i = 0; xennet_oids[i].oid; i++) {
236 supported_oids[i] = xennet_oids[i].oid;
237 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);
238 }
239 return STATUS_SUCCESS;
240 }
242 NDIS_STATUS
243 XenNet_QueryOID_GEN_DRIVER_VERSION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
244 UNREFERENCED_PARAMETER(context);
245 UNREFERENCED_PARAMETER(bytes_needed);
246 UNREFERENCED_PARAMETER(information_buffer_length);
247 *(PUSHORT)information_buffer = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
248 *bytes_written = sizeof(USHORT);
249 return STATUS_SUCCESS;
250 }
252 NDIS_STATUS
253 XenNet_QueryOID_PNP_CAPABILITIES(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
254 PNDIS_PNP_CAPABILITIES npc = (PNDIS_PNP_CAPABILITIES)information_buffer;
255 UNREFERENCED_PARAMETER(context);
256 UNREFERENCED_PARAMETER(information_buffer_length);
257 UNREFERENCED_PARAMETER(bytes_needed);
258 npc->Flags = 0;
259 npc->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
260 npc->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
261 npc->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
262 *bytes_written = sizeof(NDIS_PNP_CAPABILITIES);
263 return STATUS_SUCCESS;
264 }
266 NDIS_STATUS
267 XenNet_QueryOID_PNP_QUERY_POWER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
268 UNREFERENCED_PARAMETER(context);
269 UNREFERENCED_PARAMETER(information_buffer);
270 UNREFERENCED_PARAMETER(information_buffer_length);
271 UNREFERENCED_PARAMETER(bytes_written);
272 UNREFERENCED_PARAMETER(bytes_needed);
273 /* all we need to do here is return STATUS_SUCCESS to acknowledge - SET_POWER will happen later */
274 return STATUS_SUCCESS;
275 }
277 NDIS_STATUS
278 XenNet_SetOID_GEN_PROTOCOL_OPTIONS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
279 UNREFERENCED_PARAMETER(context);
280 UNREFERENCED_PARAMETER(information_buffer);
281 UNREFERENCED_PARAMETER(information_buffer_length);
282 UNREFERENCED_PARAMETER(bytes_read);
283 UNREFERENCED_PARAMETER(bytes_needed);
284 /* nothing useful here */
285 return STATUS_SUCCESS;
286 }
288 NDIS_STATUS
289 XenNet_QueryOID_TCP_TASK_OFFLOAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
290 struct xennet_info *xi = context;
291 PNDIS_TASK_OFFLOAD_HEADER ntoh;
292 PNDIS_TASK_OFFLOAD nto;
293 PNDIS_TASK_TCP_IP_CHECKSUM nttic;
294 PNDIS_TASK_TCP_LARGE_SEND nttls;
296 *bytes_needed = sizeof(NDIS_TASK_OFFLOAD_HEADER);
298 if (xi->backend_csum_supported)
299 *bytes_needed += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
301 if (xi->backend_gso_value)
302 *bytes_needed += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + sizeof(NDIS_TASK_TCP_LARGE_SEND);
304 if (*bytes_needed > information_buffer_length)
305 return NDIS_STATUS_BUFFER_TOO_SHORT;
307 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)information_buffer;
308 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
309 || ntoh->Size != sizeof(*ntoh)
310 || !(ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation
311 || (ntoh->EncapsulationFormat.Encapsulation == UNSPECIFIED_Encapsulation
312 && ntoh->EncapsulationFormat.EncapsulationHeaderSize == XN_HDR_SIZE))) {
313 return NDIS_STATUS_NOT_SUPPORTED;
314 }
316 ntoh->OffsetFirstTask = 0;
317 nto = NULL;
319 if (xi->backend_csum_supported) {
320 if (ntoh->OffsetFirstTask == 0) {
321 ntoh->OffsetFirstTask = ntoh->Size;
322 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
323 } else {
324 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
325 + nto->TaskBufferLength;
326 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
327 }
328 /* fill in first nto */
329 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
330 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
331 nto->Task = TcpIpChecksumNdisTask;
332 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
334 FUNCTION_MSG("config_csum enabled\n");
335 FUNCTION_MSG("nto = %p\n", nto);
336 FUNCTION_MSG("nto->Size = %d\n", nto->Size);
337 FUNCTION_MSG("nto->TaskBufferLength = %d\n", nto->TaskBufferLength);
339 /* fill in checksum offload struct */
340 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
341 nttic->V4Transmit.IpChecksum = 0;
342 nttic->V4Transmit.IpOptionsSupported = 0;
343 nttic->V4Transmit.TcpChecksum = 1;
344 nttic->V4Transmit.TcpOptionsSupported = 1;
345 nttic->V4Transmit.UdpChecksum = 1;
346 nttic->V4Receive.IpChecksum = 1;
347 nttic->V4Receive.IpOptionsSupported = 1;
348 nttic->V4Receive.TcpChecksum = 1;
349 nttic->V4Receive.TcpOptionsSupported = 1;
350 nttic->V4Receive.UdpChecksum = 1;
351 nttic->V6Transmit.IpOptionsSupported = 0;
352 nttic->V6Transmit.TcpOptionsSupported = 0;
353 nttic->V6Transmit.TcpChecksum = 0;
354 nttic->V6Transmit.UdpChecksum = 0;
355 nttic->V6Receive.IpOptionsSupported = 0;
356 nttic->V6Receive.TcpOptionsSupported = 0;
357 nttic->V6Receive.TcpChecksum = 0;
358 nttic->V6Receive.UdpChecksum = 0;
359 }
360 if (xi->backend_gso_value) {
361 if (ntoh->OffsetFirstTask == 0) {
362 ntoh->OffsetFirstTask = ntoh->Size;
363 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
364 } else {
365 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
366 + nto->TaskBufferLength;
367 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
368 }
370 /* fill in second nto */
371 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
372 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
373 nto->Task = TcpLargeSendNdisTask;
374 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
376 FUNCTION_MSG("config_gso enabled\n");
377 FUNCTION_MSG("nto = %p\n", nto);
378 FUNCTION_MSG("nto->Size = %d\n", nto->Size);
379 FUNCTION_MSG("nto->TaskBufferLength = %d\n", nto->TaskBufferLength);
381 /* fill in large send struct */
382 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
383 nttls->Version = 0;
384 nttls->MaxOffLoadSize = xi->backend_gso_value;
385 nttls->MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
386 nttls->TcpOptions = FALSE; /* linux can't handle this */
387 nttls->IpOptions = FALSE; /* linux can't handle this */
388 FUNCTION_MSG("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions));
389 }
391 if (nto)
392 nto->OffsetNextTask = 0; /* last one */
394 *bytes_written = *bytes_needed;
395 return STATUS_SUCCESS;
396 }
398 NDIS_STATUS
399 XenNet_SetOID_TCP_TASK_OFFLOAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
400 struct xennet_info *xi = context;
401 PNDIS_TASK_OFFLOAD_HEADER ntoh;
402 PNDIS_TASK_OFFLOAD nto;
403 PNDIS_TASK_TCP_IP_CHECKSUM nttic = NULL;
404 PNDIS_TASK_TCP_LARGE_SEND nttls = NULL;
405 ULONG offset;
407 UNREFERENCED_PARAMETER(bytes_needed);
408 UNREFERENCED_PARAMETER(information_buffer_length);
410 // we should disable everything here, then enable what has been set
411 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)information_buffer;
412 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION) {
413 FUNCTION_MSG("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION);
414 return NDIS_STATUS_INVALID_DATA;
415 }
416 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER)) {
417 FUNCTION_MSG("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER));
418 return NDIS_STATUS_INVALID_DATA;
419 }
420 *bytes_read = sizeof(NDIS_TASK_OFFLOAD_HEADER);
421 offset = ntoh->OffsetFirstTask;
422 nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
423 while (offset != 0) {
424 *bytes_read += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
425 nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
426 switch (nto->Task) {
427 case TcpIpChecksumNdisTask:
428 *bytes_read += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
429 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
430 FUNCTION_MSG("TcpIpChecksumNdisTask\n");
431 FUNCTION_MSG(" V4Transmit.IpOptionsSupported = %d\n", nttic->V4Transmit.IpOptionsSupported);
432 FUNCTION_MSG(" V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported);
433 FUNCTION_MSG(" V4Transmit.TcpChecksum = %d\n", nttic->V4Transmit.TcpChecksum);
434 FUNCTION_MSG(" V4Transmit.UdpChecksum = %d\n", nttic->V4Transmit.UdpChecksum);
435 FUNCTION_MSG(" V4Transmit.IpChecksum = %d\n", nttic->V4Transmit.IpChecksum);
436 FUNCTION_MSG(" V4Receive.IpOptionsSupported = %d\n", nttic->V4Receive.IpOptionsSupported);
437 FUNCTION_MSG(" V4Receive.TcpOptionsSupported = %d\n", nttic->V4Receive.TcpOptionsSupported);
438 FUNCTION_MSG(" V4Receive.TcpChecksum = %d\n", nttic->V4Receive.TcpChecksum);
439 FUNCTION_MSG(" V4Receive.UdpChecksum = %d\n", nttic->V4Receive.UdpChecksum);
440 FUNCTION_MSG(" V4Receive.IpChecksum = %d\n", nttic->V4Receive.IpChecksum);
441 FUNCTION_MSG(" V6Transmit.IpOptionsSupported = %d\n", nttic->V6Transmit.IpOptionsSupported);
442 FUNCTION_MSG(" V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported);
443 FUNCTION_MSG(" V6Transmit.TcpChecksum = %d\n", nttic->V6Transmit.TcpChecksum);
444 FUNCTION_MSG(" V6Transmit.UdpChecksum = %d\n", nttic->V6Transmit.UdpChecksum);
445 FUNCTION_MSG(" V6Receive.IpOptionsSupported = %d\n", nttic->V6Receive.IpOptionsSupported);
446 FUNCTION_MSG(" V6Receive.TcpOptionsSupported = %d\n", nttic->V6Receive.TcpOptionsSupported);
447 FUNCTION_MSG(" V6Receive.TcpChecksum = %d\n", nttic->V6Receive.TcpChecksum);
448 FUNCTION_MSG(" V6Receive.UdpChecksum = %d\n", nttic->V6Receive.UdpChecksum);
449 /* check for stuff we outright don't support */
450 if (nttic->V6Transmit.IpOptionsSupported ||
451 nttic->V6Transmit.TcpOptionsSupported ||
452 nttic->V6Transmit.TcpChecksum ||
453 nttic->V6Transmit.UdpChecksum ||
454 nttic->V6Receive.IpOptionsSupported ||
455 nttic->V6Receive.TcpOptionsSupported ||
456 nttic->V6Receive.TcpChecksum ||
457 nttic->V6Receive.UdpChecksum) {
458 FUNCTION_MSG("IPv6 offload not supported\n");
459 return NDIS_STATUS_INVALID_DATA;
460 }
461 if (nttic->V4Transmit.IpOptionsSupported || nttic->V4Transmit.IpChecksum) {
462 FUNCTION_MSG("IPv4 IP Transmit offload not supported\n");
463 return NDIS_STATUS_INVALID_DATA;
464 }
465 if (nttic->V4Receive.IpOptionsSupported && !nttic->V4Receive.IpChecksum) {
466 FUNCTION_MSG("Invalid combination\n");
467 return NDIS_STATUS_INVALID_DATA;
468 }
469 if (nttic->V4Transmit.TcpOptionsSupported && !nttic->V4Transmit.TcpChecksum) {
470 FUNCTION_MSG("Invalid combination\n");
471 return NDIS_STATUS_INVALID_DATA;
472 }
473 if (nttic->V4Receive.TcpOptionsSupported && !nttic->V4Receive.TcpChecksum) {
474 FUNCTION_MSG("Invalid combination\n");
475 return NDIS_STATUS_INVALID_DATA;
476 }
477 break;
478 case TcpLargeSendNdisTask:
479 *bytes_read += sizeof(NDIS_TASK_TCP_LARGE_SEND);
480 FUNCTION_MSG("TcpLargeSendNdisTask\n");
481 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
482 FUNCTION_MSG(" MaxOffLoadSize = %d\n", nttls->MaxOffLoadSize);
483 FUNCTION_MSG(" MinSegmentCount = %d\n", nttls->MinSegmentCount);
484 FUNCTION_MSG(" TcpOptions = %d\n", nttls->TcpOptions);
485 FUNCTION_MSG(" IpOptions = %d\n", nttls->IpOptions);
486 if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS) {
487 FUNCTION_MSG("MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS);
488 return NDIS_STATUS_INVALID_DATA;
489 }
490 if (nttls->IpOptions) {
491 FUNCTION_MSG("IpOptions not supported\n");
492 return NDIS_STATUS_INVALID_DATA;
493 }
494 if (nttls->TcpOptions) {
495 FUNCTION_MSG("TcpOptions not supported\n");
496 return NDIS_STATUS_INVALID_DATA;
497 }
498 break;
499 default:
500 FUNCTION_MSG("Unknown Task %d\n", nto->Task);
501 }
502 offset = nto->OffsetNextTask;
503 }
504 if (nttic != NULL) {
505 xi->current_csum_supported = TRUE;
506 xi->setting_csum = *nttic;
507 } else {
508 RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
509 FUNCTION_MSG("csum offload disabled\n", nto->Task);
510 }
511 if (nttls != NULL)
512 xi->current_gso_value = nttls->MaxOffLoadSize;
513 else {
514 xi->current_gso_value = 0;
515 FUNCTION_MSG("LSO disabled\n", nto->Task);
516 }
517 return STATUS_SUCCESS;
518 }
519 #else
520 NDIS_STATUS
521 XenNet_QueryOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
522 PNDIS_INTERRUPT_MODERATION_PARAMETERS nimp;
523 UNREFERENCED_PARAMETER(context);
524 UNREFERENCED_PARAMETER(bytes_needed);
525 UNREFERENCED_PARAMETER(information_buffer_length);
526 nimp = (PNDIS_INTERRUPT_MODERATION_PARAMETERS)information_buffer;
527 nimp->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
528 nimp->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
529 nimp->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
530 nimp->Flags = 0;
531 nimp->InterruptModeration = NdisInterruptModerationNotSupported;
532 *bytes_written = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
533 return STATUS_SUCCESS;
534 }
536 NDIS_STATUS
537 XenNet_SetOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
538 UNREFERENCED_PARAMETER(context);
539 UNREFERENCED_PARAMETER(information_buffer);
540 UNREFERENCED_PARAMETER(information_buffer_length);
541 UNREFERENCED_PARAMETER(bytes_read);
542 UNREFERENCED_PARAMETER(bytes_needed);
543 return STATUS_NOT_SUPPORTED;
544 }
546 NDIS_STATUS
547 XenNet_QueryOID_GEN_STATISTICS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
548 struct xennet_info *xi = context;
549 UNREFERENCED_PARAMETER(bytes_needed);
550 UNREFERENCED_PARAMETER(information_buffer_length);
552 NdisMoveMemory(information_buffer, &xi->stats, sizeof(NDIS_STATISTICS_INFO));
553 *bytes_written = sizeof(NDIS_STATISTICS_INFO);
554 return STATUS_SUCCESS;
555 }
557 NDIS_STATUS
558 XenNet_SetOID_OFFLOAD_ENCAPSULATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
559 struct xennet_info *xi = context;
560 PNDIS_OFFLOAD_ENCAPSULATION noe = (PNDIS_OFFLOAD_ENCAPSULATION)information_buffer;
561 UNREFERENCED_PARAMETER(bytes_needed);
562 UNREFERENCED_PARAMETER(information_buffer_length);
563 /* mostly assume that NDIS vets the settings for us */
564 if (noe->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3) {
565 FUNCTION_MSG("Unknown Encapsulation Type %d\n", noe->IPv4.EncapsulationType);
566 return NDIS_STATUS_NOT_SUPPORTED;
567 }
569 switch(noe->IPv4.Enabled) {
570 case NDIS_OFFLOAD_SET_ON:
571 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_ON\n");
572 xi->current_csum_supported = xi->backend_csum_supported && xi->frontend_csum_supported;
573 xi->current_gso_value = min(xi->backend_csum_supported, xi->frontend_csum_supported);
574 break;
575 case NDIS_OFFLOAD_SET_OFF:
576 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_OFF\n");
577 xi->current_csum_supported = FALSE;
578 xi->current_gso_value = 0;
579 break;
580 case NDIS_OFFLOAD_SET_NO_CHANGE:
581 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
582 break;
583 }
584 FUNCTION_MSG(" IPv4.HeaderSize = %d\n", noe->IPv4.HeaderSize);
585 FUNCTION_MSG(" IPv6.EncapsulationType = %d\n", noe->IPv6.EncapsulationType);
586 switch(noe->IPv6.Enabled) {
587 case NDIS_OFFLOAD_SET_ON:
588 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_ON (this is an error)\n");
589 break;
590 case NDIS_OFFLOAD_SET_OFF:
591 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_OFF\n");
592 break;
593 case NDIS_OFFLOAD_SET_NO_CHANGE:
594 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
595 break;
596 }
597 *bytes_read = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
598 FUNCTION_MSG(" IPv6.HeaderSize = %d\n", noe->IPv6.HeaderSize);
599 return NDIS_STATUS_SUCCESS;
600 }
601 #endif
603 NDIS_STATUS
604 XenNet_SetOID_PNP_SET_POWER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
605 UNREFERENCED_PARAMETER(context);
606 UNREFERENCED_PARAMETER(information_buffer);
607 UNREFERENCED_PARAMETER(information_buffer_length);
608 UNREFERENCED_PARAMETER(bytes_read);
609 UNREFERENCED_PARAMETER(bytes_needed);
610 return STATUS_NOT_SUPPORTED;
611 }
613 NDIS_STATUS
614 XenNet_SetOID_GEN_NETWORK_LAYER_ADDRESSES(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
615 PNETWORK_ADDRESS_LIST nal = information_buffer;
616 PNETWORK_ADDRESS na;
617 PNETWORK_ADDRESS_IP ip;
618 int i;
620 UNREFERENCED_PARAMETER(context);
621 UNREFERENCED_PARAMETER(bytes_read);
622 UNREFERENCED_PARAMETER(bytes_needed);
623 FUNCTION_MSG("AddressType = %d\n", nal->AddressType);
624 FUNCTION_MSG("AddressCount = %d\n", nal->AddressCount);
625 if (nal->AddressCount == 0) {
626 // remove addresses of AddressType type
627 } else {
628 na = nal->Address;
629 for (i = 0; i < nal->AddressCount; i++) {
630 if ((ULONG_PTR)na - (ULONG_PTR)nal + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength > information_buffer_length) {
631 FUNCTION_MSG("Out of bounds\n");
632 return NDIS_STATUS_INVALID_DATA;
633 }
634 switch(na->AddressType) {
635 case NDIS_PROTOCOL_ID_TCP_IP:
636 FUNCTION_MSG("Address[%d].Type = NDIS_PROTOCOL_ID_TCP_IP\n", i);
637 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
638 if (na->AddressLength != NETWORK_ADDRESS_LENGTH_IP) {
639 FUNCTION_MSG("Length is invalid\n");
640 break;
641 }
642 ip = (PNETWORK_ADDRESS_IP)na->Address;
643 FUNCTION_MSG("Address[%d].in_addr = %d.%d.%d.%d\n", i, ip->in_addr & 0xff, (ip->in_addr >> 8) & 0xff, (ip->in_addr >> 16) & 0xff, (ip->in_addr >> 24) & 0xff);
644 break;
645 default:
646 FUNCTION_MSG("Address[%d].Type = %d\n", i, na->AddressType);
647 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
648 break;
649 }
650 na = (PNETWORK_ADDRESS)((PUCHAR)na + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength);
651 }
652 }
654 return NDIS_STATUS_SUCCESS;
655 }
657 NDIS_STATUS
658 XenNet_SetOID_GEN_MACHINE_NAME(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
659 UNICODE_STRING name;
660 UNREFERENCED_PARAMETER(context);
661 UNREFERENCED_PARAMETER(bytes_read);
662 UNREFERENCED_PARAMETER(bytes_needed);
664 name.Length = (USHORT)information_buffer_length;
665 name.MaximumLength = (USHORT)information_buffer_length;
666 name.Buffer = information_buffer;
667 FUNCTION_MSG("name = %wZ\n", &name);
668 return NDIS_STATUS_SUCCESS;
669 }
671 struct xennet_oids_t xennet_oids[] = {
672 DEF_OID_QUERY_ULONG(OID_GEN_HARDWARE_STATUS),
674 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BUFFER_SPACE),
675 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BUFFER_SPACE),
676 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BLOCK_SIZE),
677 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BLOCK_SIZE),
679 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_ID),
680 DEF_OID_QUERY(OID_GEN_VENDOR_DESCRIPTION, sizeof(XN_VENDOR_DESC)),
681 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_DRIVER_VERSION),
683 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_PACKET_FILTER),
684 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_LOOKAHEAD),
685 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_TOTAL_SIZE),
687 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_SEND_PACKETS),
688 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_SUPPORTED),
689 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_IN_USE),
690 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_LOOKAHEAD),
692 /* general optional */
693 DEF_OID_SET(OID_GEN_NETWORK_LAYER_ADDRESSES, FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)),
694 DEF_OID_SET(OID_GEN_MACHINE_NAME, 0),
696 /* power */
697 DEF_OID_SET_ULONG(OID_PNP_SET_POWER),
699 /* stats */
700 DEF_OID_QUERY_STAT(OID_GEN_XMIT_OK),
701 DEF_OID_QUERY_STAT(OID_GEN_RCV_OK),
702 DEF_OID_QUERY_STAT(OID_GEN_XMIT_ERROR),
703 DEF_OID_QUERY_STAT(OID_GEN_RCV_ERROR),
704 DEF_OID_QUERY_STAT(OID_GEN_RCV_NO_BUFFER),
705 DEF_OID_QUERY_STAT(OID_802_3_RCV_ERROR_ALIGNMENT),
706 DEF_OID_QUERY_STAT(OID_802_3_XMIT_ONE_COLLISION),
707 DEF_OID_QUERY_STAT(OID_802_3_XMIT_MORE_COLLISIONS),
708 DEF_OID_NONE(OID_IP4_OFFLOAD_STATS),
709 DEF_OID_NONE(OID_IP6_OFFLOAD_STATS),
711 /* media-specific */
712 DEF_OID_QUERY(OID_802_3_PERMANENT_ADDRESS, 6),
713 DEF_OID_QUERY(OID_802_3_CURRENT_ADDRESS, 6),
714 DEF_OID_QUERYSET(OID_802_3_MULTICAST_LIST, 0),
715 DEF_OID_QUERY_ULONG(OID_802_3_MAXIMUM_LIST_SIZE),
717 #if NTDDI_VERSION < NTDDI_VISTA
718 DEF_OID_QUERY(OID_GEN_SUPPORTED_LIST, 0),
719 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_FRAME_SIZE),
720 DEF_OID_QUERY_ULONG(OID_GEN_LINK_SPEED),
721 DEF_OID_QUERY(OID_GEN_DRIVER_VERSION, sizeof(USHORT)),
722 DEF_OID_QUERY_ULONG(OID_GEN_MAC_OPTIONS),
723 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_CONNECT_STATUS),
724 DEF_OID_QUERYSET(OID_TCP_TASK_OFFLOAD, 0),
725 DEF_OID_QUERY(OID_PNP_CAPABILITIES, sizeof(NDIS_PNP_CAPABILITIES)),
726 DEF_OID_QUERY(OID_PNP_QUERY_POWER, 0),
727 DEF_OID_SET(OID_GEN_PROTOCOL_OPTIONS, 0),
728 #else
729 DEF_OID_SET(OID_GEN_LINK_PARAMETERS, sizeof(NDIS_LINK_PARAMETERS)),
730 DEF_OID_QUERYSET(OID_GEN_INTERRUPT_MODERATION, sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS)),
731 DEF_OID_SET(OID_OFFLOAD_ENCAPSULATION, sizeof(NDIS_OFFLOAD_ENCAPSULATION)),
732 DEF_OID_QUERY(OID_GEN_STATISTICS, sizeof(NDIS_STATISTICS_INFO)),
733 #endif
734 {0, "", 0, NULL, NULL}
735 };
737 //static NDIS_OID supported_oids[ARRAY_SIZE(xennet_oids)];
738 #if NTDDI_VERSION < NTDDI_VISTA
739 NDIS_STATUS
740 XenNet_SetInformation(
741 NDIS_HANDLE adapter_context,
742 NDIS_OID oid,
743 PVOID information_buffer,
744 ULONG information_buffer_length,
745 PULONG bytes_read,
746 PULONG bytes_needed) {
747 NTSTATUS status;
748 int i;
750 FUNCTION_ENTER();
751 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
753 if (!xennet_oids[i].oid) {
754 FUNCTION_MSG("Unsupported OID %08x\n", oid);
755 return NDIS_STATUS_NOT_SUPPORTED;
756 }
757 if (information_buffer_length < xennet_oids[i].min_length) {
758 FUNCTION_MSG("%s Set InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length);
759 *bytes_needed = xennet_oids[i].min_length;
760 return NDIS_STATUS_BUFFER_TOO_SHORT;
761 }
762 if (!xennet_oids[i].set_routine) {
763 FUNCTION_MSG("%s Set not supported\n", xennet_oids[i].oid_name);
764 return NDIS_STATUS_NOT_SUPPORTED;
765 }
766 FUNCTION_MSG("%s\n", xennet_oids[i].oid_name);
767 status = xennet_oids[i].set_routine(adapter_context, information_buffer, information_buffer_length, bytes_read, bytes_needed);
768 FUNCTION_EXIT();
769 return status;
770 }
772 NDIS_STATUS
773 XenNet_QueryInformation(
774 IN NDIS_HANDLE adapter_context,
775 IN NDIS_OID oid,
776 IN PVOID information_buffer,
777 IN ULONG information_buffer_length,
778 OUT PULONG bytes_written,
779 OUT PULONG bytes_needed) {
780 NTSTATUS status;
781 int i;
783 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
785 if (!xennet_oids[i].oid) {
786 FUNCTION_MSG("Unsupported OID %08x\n", oid);
787 return NDIS_STATUS_NOT_SUPPORTED;
788 }
789 if (information_buffer_length < xennet_oids[i].min_length) {
790 FUNCTION_MSG("%s Query InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length);
791 *bytes_needed = xennet_oids[i].min_length;
792 return NDIS_STATUS_BUFFER_TOO_SHORT;
793 }
794 if (!xennet_oids[i].query_routine) {
795 FUNCTION_MSG("%s Query not supported\n", xennet_oids[i].oid_name);
796 return NDIS_STATUS_NOT_SUPPORTED;
797 }
798 //FUNCTION_MSG("%s\n", xennet_oids[i].oid_name);
799 status = xennet_oids[i].query_routine(adapter_context, information_buffer, information_buffer_length, bytes_written, bytes_needed);
800 return status;
801 }
803 #else
804 NDIS_STATUS
805 XenNet_OidRequest(NDIS_HANDLE adapter_context, PNDIS_OID_REQUEST oid_request)
806 {
807 NTSTATUS status;
808 int i;
809 NDIS_OID oid;
811 //FUNCTION_ENTER();
812 switch(oid_request->RequestType)
813 {
814 case NdisRequestQueryInformation:
815 //FUNCTION_MSG("RequestType = NdisRequestQueryInformation\n");
816 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
817 break;
818 case NdisRequestSetInformation:
819 //FUNCTION_MSG("RequestType = NdisRequestSetInformation\n");
820 oid = oid_request->DATA.SET_INFORMATION.Oid;
821 break;
822 case NdisRequestQueryStatistics:
823 //FUNCTION_MSG("RequestType = NdisRequestQueryStatistics\n");
824 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
825 break;
826 default:
827 //FUNCTION_MSG("RequestType = NdisRequestQuery%d\n", oid_request->RequestType);
828 return NDIS_STATUS_NOT_SUPPORTED;
829 }
830 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
832 if (!xennet_oids[i].oid) {
833 FUNCTION_MSG("Unsupported OID %08x\n", oid);
834 return NDIS_STATUS_NOT_SUPPORTED;
835 }
836 //FUNCTION_MSG("Oid = %s\n", xennet_oids[i].oid_name);
837 switch(oid_request->RequestType)
838 {
839 case NdisRequestQueryInformation:
840 case NdisRequestQueryStatistics:
841 if (oid_request->DATA.QUERY_INFORMATION.InformationBufferLength < xennet_oids[i].min_length) {
842 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.QUERY_INFORMATION.InformationBufferLength, xennet_oids[i].min_length);
843 oid_request->DATA.QUERY_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
844 return NDIS_STATUS_BUFFER_TOO_SHORT;
845 }
846 if (!xennet_oids[i].query_routine) {
847 //FUNCTION_MSG("Operation not supported\n");
848 return NDIS_STATUS_NOT_SUPPORTED;
849 }
850 status = xennet_oids[i].query_routine(adapter_context, oid_request->DATA.QUERY_INFORMATION.InformationBuffer, oid_request->DATA.QUERY_INFORMATION.InformationBufferLength, (PULONG)&oid_request->DATA.QUERY_INFORMATION.BytesWritten, (PULONG)&oid_request->DATA.QUERY_INFORMATION.BytesNeeded);
851 break;
852 case NdisRequestSetInformation:
853 if (oid_request->DATA.SET_INFORMATION.InformationBufferLength < xennet_oids[i].min_length) {
854 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.SET_INFORMATION.InformationBufferLength, xennet_oids[i].min_length);
855 oid_request->DATA.SET_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
856 return NDIS_STATUS_BUFFER_TOO_SHORT;
857 }
858 if (!xennet_oids[i].set_routine) {
859 //FUNCTION_MSG("Operation not supported\n");
860 return NDIS_STATUS_NOT_SUPPORTED;
861 }
862 status = xennet_oids[i].set_routine(adapter_context, oid_request->DATA.SET_INFORMATION.InformationBuffer, oid_request->DATA.SET_INFORMATION.InformationBufferLength, (PULONG)&oid_request->DATA.SET_INFORMATION.BytesRead, (PULONG)&oid_request->DATA.SET_INFORMATION.BytesNeeded);
863 break;
864 default:
865 return NDIS_STATUS_NOT_SUPPORTED;
866 }
867 //FUNCTION_EXIT();
868 return status;
869 }
871 VOID
872 XenNet_CancelOidRequest(NDIS_HANDLE adapter_context, PVOID request_id)
873 {
874 UNREFERENCED_PARAMETER(adapter_context);
875 UNREFERENCED_PARAMETER(request_id);
876 FUNCTION_ENTER();
877 FUNCTION_EXIT();
878 }
879 #endif