win-pvdrivers

view xennet/xennet_oid.c @ 1099:27bd2a5a4704

License change from GPL to BSD
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 13 13:38:31 2014 +1100 (2014-03-13)
parents c21a4feb4a27
children
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
4 Copyright (c) 2014, James Harper
5 All rights reserved.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 * Neither the name of James Harper nor the
15 names of its contributors may be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL JAMES HARPER BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
30 #include "xennet.h"
32 #define DEF_OID_QUERY(oid, min_length) {oid, #oid, min_length, XenNet_Query##oid, NULL}
33 #define DEF_OID_QUERYSET(oid, min_length) {oid, #oid, min_length, XenNet_Query##oid, XenNet_Set##oid}
34 #define DEF_OID_SET(oid, min_length) {oid, #oid, min_length, NULL, XenNet_Set##oid}
35 #define DEF_OID_NONE(oid) {oid, #oid, 0, NULL, NULL} /* define this for a silent but unsupported oid */
37 #define DEF_OID_QUERY_STAT(oid) DEF_OID_QUERY(##oid, 0) /* has to be 0 so the 4/8 size works */
38 #define DEF_OID_QUERY_ULONG(oid) DEF_OID_QUERY(##oid, sizeof(ULONG))
39 #define DEF_OID_QUERYSET_ULONG(oid) DEF_OID_QUERYSET(##oid, sizeof(ULONG))
40 #define DEF_OID_SET_ULONG(oid) DEF_OID_SET(##oid, sizeof(ULONG))
42 #define DEF_OID_QUERY_ROUTINE(oid, value, length) \
43 NDIS_STATUS \
44 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
45 struct xennet_info *xi = context; \
46 UNREFERENCED_PARAMETER(xi); \
47 if (information_buffer_length < length) \
48 { \
49 *bytes_needed = length; \
50 return NDIS_STATUS_BUFFER_TOO_SHORT; \
51 } \
52 *bytes_written = length; \
53 NdisMoveMemory(information_buffer, value, length); \
54 return STATUS_SUCCESS; \
55 }
57 #define DEF_OID_QUERY_ULONG_ROUTINE(oid, value) \
58 NDIS_STATUS \
59 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
60 struct xennet_info *xi = context; \
61 UNREFERENCED_PARAMETER(xi); \
62 UNREFERENCED_PARAMETER(information_buffer_length); \
63 UNREFERENCED_PARAMETER(bytes_needed); \
64 *bytes_written = sizeof(ULONG); \
65 *(ULONG *)information_buffer = value; \
66 return STATUS_SUCCESS; \
67 }
69 #define DEF_OID_QUERY_STAT_ROUTINE(oid, value) \
70 NDIS_STATUS \
71 XenNet_Query##oid(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { \
72 struct xennet_info *xi = context; \
73 UNREFERENCED_PARAMETER(xi); \
74 if (information_buffer_length >= sizeof(ULONG64)) \
75 { \
76 *bytes_written = sizeof(ULONG64); \
77 *(ULONG64 *)information_buffer = (value); \
78 } \
79 else if (information_buffer_length >= sizeof(ULONG)) \
80 { \
81 *bytes_written = sizeof(ULONG); \
82 *bytes_needed = sizeof(ULONG64); \
83 *(ULONG *)information_buffer = (ULONG)(value); \
84 } \
85 else \
86 { \
87 *bytes_needed = sizeof(ULONG64); \
88 return NDIS_STATUS_BUFFER_TOO_SHORT; \
89 } \
90 return STATUS_SUCCESS; \
91 }
93 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_TOTAL_SIZE, xi->current_mtu_value + XN_HDR_SIZE)
94 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_PACKET_FILTER, xi->packet_filter)
95 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_LOOKAHEAD, xi->current_lookahead)
96 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BUFFER_SPACE, PAGE_SIZE * NET_TX_RING_SIZE * 4)
97 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BUFFER_SPACE, PAGE_SIZE * NET_RX_RING_SIZE * 2)
98 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BLOCK_SIZE, PAGE_SIZE)
99 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BLOCK_SIZE, PAGE_SIZE)
100 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_SEND_PACKETS, 0)
101 DEF_OID_QUERY_ULONG_ROUTINE(OID_802_3_MAXIMUM_LIST_SIZE, MULTICAST_LIST_MAX_SIZE)
102 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_HARDWARE_STATUS, (xi->device_state == DEVICE_STATE_INACTIVE || xi->device_state == DEVICE_STATE_ACTIVE)?NdisHardwareStatusReady:NdisHardwareStatusInitializing)
103 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_ID, 0xFFFFFF) // Not guaranteed to be XENSOURCE_MAC_HDR;
104 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_DRIVER_VERSION, VENDOR_DRIVER_VERSION)
105 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_SUPPORTED, NdisMedium802_3)
106 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_IN_USE, NdisMedium802_3)
107 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_LOOKAHEAD, MAX_LOOKAHEAD_LENGTH)
109 #if NTDDI_VERSION < NTDDI_VISTA
110 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_FRAME_SIZE, xi->current_mtu_value);
111 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);
112 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_CONNECT_STATUS, (xi->device_state == DEVICE_STATE_ACTIVE)?NdisMediaStateConnected:NdisMediaStateDisconnected);
113 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_LINK_SPEED, (ULONG)(MAX_LINK_SPEED / 100));
115 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_OK, xi->stat_tx_ok)
116 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_ERROR, xi->stat_tx_error)
117 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_OK, xi->stat_rx_ok)
118 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_ERROR, xi->stat_rx_error)
119 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_NO_BUFFER, xi->stat_rx_no_buffer)
120 #else
121 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_OK, xi->stats.ifHCOutUcastPkts + xi->stats.ifHCOutMulticastPkts + xi->stats.ifHCOutBroadcastPkts)
122 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_ERROR, xi->stats.ifOutErrors)
123 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_OK, xi->stats.ifHCInUcastPkts + xi->stats.ifHCInMulticastPkts + xi->stats.ifHCInBroadcastPkts)
124 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_ERROR, xi->stats.ifInErrors)
125 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_NO_BUFFER, xi->stats.ifInDiscards)
126 #endif
127 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_RCV_ERROR_ALIGNMENT, 0)
128 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_ONE_COLLISION, 0)
129 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_MORE_COLLISIONS, 0)
131 DEF_OID_QUERY_ROUTINE(OID_GEN_VENDOR_DESCRIPTION, XN_VENDOR_DESC, sizeof(XN_VENDOR_DESC))
133 DEF_OID_QUERY_ROUTINE(OID_802_3_PERMANENT_ADDRESS, xi->perm_mac_addr, ETH_ALEN)
134 DEF_OID_QUERY_ROUTINE(OID_802_3_CURRENT_ADDRESS, xi->curr_mac_addr, ETH_ALEN)
136 DEF_OID_QUERY_ROUTINE(OID_802_3_MULTICAST_LIST, xi->multicast_list, xi->multicast_list_size * 6)
138 NDIS_STATUS
139 XenNet_SetOID_802_3_MULTICAST_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
140 struct xennet_info *xi = context;
141 UCHAR *multicast_list;
142 int i;
143 UNREFERENCED_PARAMETER(bytes_read);
144 UNREFERENCED_PARAMETER(bytes_needed);
146 if (information_buffer_length > MULTICAST_LIST_MAX_SIZE * 6) {
147 return NDIS_STATUS_MULTICAST_FULL;
148 }
150 if (information_buffer_length % 6 != 0) {
151 return NDIS_STATUS_MULTICAST_FULL;
152 }
153 multicast_list = information_buffer;
154 for (i = 0; i < (int)information_buffer_length / 6; i++) {
155 if (!(multicast_list[i * 6 + 0] & 0x01)) {
156 FUNCTION_MSG("Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i,
157 (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1],
158 (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3],
159 (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]);
160 /* 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... */
161 }
162 }
163 memcpy(xi->multicast_list, multicast_list, information_buffer_length);
164 xi->multicast_list_size = information_buffer_length / 6;
165 return NDIS_STATUS_SUCCESS;
166 }
168 NDIS_STATUS
169 XenNet_SetOID_GEN_CURRENT_PACKET_FILTER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
170 struct xennet_info *xi = context;
171 PULONG data = information_buffer;
173 UNREFERENCED_PARAMETER(information_buffer_length);
174 *bytes_needed = sizeof(ULONG64);
175 if (*data & NDIS_PACKET_TYPE_DIRECTED)
176 FUNCTION_MSG("NDIS_PACKET_TYPE_DIRECTED\n");
177 if (*data & NDIS_PACKET_TYPE_MULTICAST)
178 FUNCTION_MSG("NDIS_PACKET_TYPE_MULTICAST\n");
179 if (*data & NDIS_PACKET_TYPE_ALL_MULTICAST)
180 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_MULTICAST\n");
181 if (*data & NDIS_PACKET_TYPE_BROADCAST)
182 FUNCTION_MSG("NDIS_PACKET_TYPE_BROADCAST\n");
183 if (*data & NDIS_PACKET_TYPE_PROMISCUOUS)
184 FUNCTION_MSG("NDIS_PACKET_TYPE_PROMISCUOUS\n");
185 if (*data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
186 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n");
187 if (*data & NDIS_PACKET_TYPE_ALL_LOCAL)
188 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n");
189 if (*data & NDIS_PACKET_TYPE_FUNCTIONAL)
190 FUNCTION_MSG("NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n");
191 if (*data & NDIS_PACKET_TYPE_GROUP)
192 FUNCTION_MSG("NDIS_PACKET_TYPE_GROUP (not supported)\n");
193 if (*data & ~SUPPORTED_PACKET_FILTERS) {
194 FUNCTION_MSG("returning NDIS_STATUS_NOT_SUPPORTED\n");
195 return NDIS_STATUS_NOT_SUPPORTED;
196 }
197 xi->packet_filter = *(ULONG *)data;
198 *bytes_read = sizeof(ULONG);
199 return NDIS_STATUS_SUCCESS;
200 }
202 NDIS_STATUS
203 XenNet_SetOID_GEN_CURRENT_LOOKAHEAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
204 struct xennet_info *xi = context;
205 PULONG data = information_buffer;
206 UNREFERENCED_PARAMETER(information_buffer_length);
207 UNREFERENCED_PARAMETER(bytes_read);
208 UNREFERENCED_PARAMETER(bytes_needed);
209 xi->current_lookahead = *(ULONG *)data;
210 FUNCTION_MSG("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi);
211 return NDIS_STATUS_SUCCESS;
212 }
214 NDIS_STATUS
215 XenNet_SetOID_GEN_LINK_PARAMETERS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
216 UNREFERENCED_PARAMETER(context);
217 UNREFERENCED_PARAMETER(information_buffer);
218 UNREFERENCED_PARAMETER(information_buffer_length);
219 UNREFERENCED_PARAMETER(bytes_read);
220 UNREFERENCED_PARAMETER(bytes_needed);
221 return STATUS_NOT_SUPPORTED;
222 }
224 #if NTDDI_VERSION < NTDDI_VISTA
225 NDIS_STATUS
226 XenNet_QueryOID_GEN_SUPPORTED_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
227 PNDIS_OID supported_oids;
228 int i;
230 UNREFERENCED_PARAMETER(context);
231 UNREFERENCED_PARAMETER(information_buffer);
232 UNREFERENCED_PARAMETER(information_buffer_length);
233 UNREFERENCED_PARAMETER(bytes_written);
234 UNREFERENCED_PARAMETER(bytes_needed);
236 for (i = 0; xennet_oids[i].oid; i++);
238 if (information_buffer_length < sizeof(NDIS_OID) * i) {
239 *bytes_needed = sizeof(NDIS_OID) * i;
240 return NDIS_STATUS_BUFFER_TOO_SHORT;
241 }
243 supported_oids = information_buffer;
244 for (i = 0; xennet_oids[i].oid; i++) {
245 supported_oids[i] = xennet_oids[i].oid;
246 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);
247 }
248 return STATUS_SUCCESS;
249 }
251 NDIS_STATUS
252 XenNet_QueryOID_GEN_DRIVER_VERSION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
253 UNREFERENCED_PARAMETER(context);
254 UNREFERENCED_PARAMETER(bytes_needed);
255 UNREFERENCED_PARAMETER(information_buffer_length);
256 *(PUSHORT)information_buffer = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
257 *bytes_written = sizeof(USHORT);
258 return STATUS_SUCCESS;
259 }
261 NDIS_STATUS
262 XenNet_QueryOID_PNP_CAPABILITIES(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
263 PNDIS_PNP_CAPABILITIES npc = (PNDIS_PNP_CAPABILITIES)information_buffer;
264 UNREFERENCED_PARAMETER(context);
265 UNREFERENCED_PARAMETER(information_buffer_length);
266 UNREFERENCED_PARAMETER(bytes_needed);
267 npc->Flags = 0;
268 npc->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
269 npc->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
270 npc->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
271 *bytes_written = sizeof(NDIS_PNP_CAPABILITIES);
272 return STATUS_SUCCESS;
273 }
275 NDIS_STATUS
276 XenNet_QueryOID_PNP_QUERY_POWER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
277 UNREFERENCED_PARAMETER(context);
278 UNREFERENCED_PARAMETER(information_buffer);
279 UNREFERENCED_PARAMETER(information_buffer_length);
280 UNREFERENCED_PARAMETER(bytes_written);
281 UNREFERENCED_PARAMETER(bytes_needed);
282 /* all we need to do here is return STATUS_SUCCESS to acknowledge - SET_POWER will happen later */
283 return STATUS_SUCCESS;
284 }
286 NDIS_STATUS
287 XenNet_SetOID_GEN_PROTOCOL_OPTIONS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
288 UNREFERENCED_PARAMETER(context);
289 UNREFERENCED_PARAMETER(information_buffer);
290 UNREFERENCED_PARAMETER(information_buffer_length);
291 UNREFERENCED_PARAMETER(bytes_read);
292 UNREFERENCED_PARAMETER(bytes_needed);
293 /* nothing useful here */
294 return STATUS_SUCCESS;
295 }
297 NDIS_STATUS
298 XenNet_QueryOID_TCP_TASK_OFFLOAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
299 struct xennet_info *xi = context;
300 PNDIS_TASK_OFFLOAD_HEADER ntoh;
301 PNDIS_TASK_OFFLOAD nto;
302 PNDIS_TASK_TCP_IP_CHECKSUM nttic;
303 PNDIS_TASK_TCP_LARGE_SEND nttls;
305 *bytes_needed = sizeof(NDIS_TASK_OFFLOAD_HEADER);
307 if (xi->backend_csum_supported)
308 *bytes_needed += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
310 if (xi->backend_gso_value)
311 *bytes_needed += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) + sizeof(NDIS_TASK_TCP_LARGE_SEND);
313 if (*bytes_needed > information_buffer_length)
314 return NDIS_STATUS_BUFFER_TOO_SHORT;
316 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)information_buffer;
317 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
318 || ntoh->Size != sizeof(*ntoh)
319 || !(ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation
320 || (ntoh->EncapsulationFormat.Encapsulation == UNSPECIFIED_Encapsulation
321 && ntoh->EncapsulationFormat.EncapsulationHeaderSize == XN_HDR_SIZE))) {
322 return NDIS_STATUS_NOT_SUPPORTED;
323 }
325 ntoh->OffsetFirstTask = 0;
326 nto = NULL;
328 if (xi->backend_csum_supported) {
329 if (ntoh->OffsetFirstTask == 0) {
330 ntoh->OffsetFirstTask = ntoh->Size;
331 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
332 } else {
333 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
334 + nto->TaskBufferLength;
335 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
336 }
337 /* fill in first nto */
338 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
339 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
340 nto->Task = TcpIpChecksumNdisTask;
341 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
343 FUNCTION_MSG("config_csum enabled\n");
344 FUNCTION_MSG("nto = %p\n", nto);
345 FUNCTION_MSG("nto->Size = %d\n", nto->Size);
346 FUNCTION_MSG("nto->TaskBufferLength = %d\n", nto->TaskBufferLength);
348 /* fill in checksum offload struct */
349 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
350 nttic->V4Transmit.IpChecksum = 0;
351 nttic->V4Transmit.IpOptionsSupported = 0;
352 nttic->V4Transmit.TcpChecksum = 1;
353 nttic->V4Transmit.TcpOptionsSupported = 1;
354 nttic->V4Transmit.UdpChecksum = 1;
355 nttic->V4Receive.IpChecksum = 1;
356 nttic->V4Receive.IpOptionsSupported = 1;
357 nttic->V4Receive.TcpChecksum = 1;
358 nttic->V4Receive.TcpOptionsSupported = 1;
359 nttic->V4Receive.UdpChecksum = 1;
360 nttic->V6Transmit.IpOptionsSupported = 0;
361 nttic->V6Transmit.TcpOptionsSupported = 0;
362 nttic->V6Transmit.TcpChecksum = 0;
363 nttic->V6Transmit.UdpChecksum = 0;
364 nttic->V6Receive.IpOptionsSupported = 0;
365 nttic->V6Receive.TcpOptionsSupported = 0;
366 nttic->V6Receive.TcpChecksum = 0;
367 nttic->V6Receive.UdpChecksum = 0;
368 }
369 if (xi->backend_gso_value) {
370 if (ntoh->OffsetFirstTask == 0) {
371 ntoh->OffsetFirstTask = ntoh->Size;
372 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
373 } else {
374 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
375 + nto->TaskBufferLength;
376 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
377 }
379 /* fill in second nto */
380 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
381 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
382 nto->Task = TcpLargeSendNdisTask;
383 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
385 FUNCTION_MSG("config_gso enabled\n");
386 FUNCTION_MSG("nto = %p\n", nto);
387 FUNCTION_MSG("nto->Size = %d\n", nto->Size);
388 FUNCTION_MSG("nto->TaskBufferLength = %d\n", nto->TaskBufferLength);
390 /* fill in large send struct */
391 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
392 nttls->Version = 0;
393 nttls->MaxOffLoadSize = xi->backend_gso_value;
394 nttls->MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
395 nttls->TcpOptions = FALSE; /* linux can't handle this */
396 nttls->IpOptions = FALSE; /* linux can't handle this */
397 FUNCTION_MSG("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions));
398 }
400 if (nto)
401 nto->OffsetNextTask = 0; /* last one */
403 *bytes_written = *bytes_needed;
404 return STATUS_SUCCESS;
405 }
407 NDIS_STATUS
408 XenNet_SetOID_TCP_TASK_OFFLOAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
409 struct xennet_info *xi = context;
410 PNDIS_TASK_OFFLOAD_HEADER ntoh;
411 PNDIS_TASK_OFFLOAD nto;
412 PNDIS_TASK_TCP_IP_CHECKSUM nttic = NULL;
413 PNDIS_TASK_TCP_LARGE_SEND nttls = NULL;
414 ULONG offset;
416 UNREFERENCED_PARAMETER(bytes_needed);
417 UNREFERENCED_PARAMETER(information_buffer_length);
419 // we should disable everything here, then enable what has been set
420 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)information_buffer;
421 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION) {
422 FUNCTION_MSG("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION);
423 return NDIS_STATUS_INVALID_DATA;
424 }
425 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER)) {
426 FUNCTION_MSG("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER));
427 return NDIS_STATUS_INVALID_DATA;
428 }
429 *bytes_read = sizeof(NDIS_TASK_OFFLOAD_HEADER);
430 offset = ntoh->OffsetFirstTask;
431 nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
432 while (offset != 0) {
433 *bytes_read += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
434 nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
435 switch (nto->Task) {
436 case TcpIpChecksumNdisTask:
437 *bytes_read += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
438 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
439 FUNCTION_MSG("TcpIpChecksumNdisTask\n");
440 FUNCTION_MSG(" V4Transmit.IpOptionsSupported = %d\n", nttic->V4Transmit.IpOptionsSupported);
441 FUNCTION_MSG(" V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported);
442 FUNCTION_MSG(" V4Transmit.TcpChecksum = %d\n", nttic->V4Transmit.TcpChecksum);
443 FUNCTION_MSG(" V4Transmit.UdpChecksum = %d\n", nttic->V4Transmit.UdpChecksum);
444 FUNCTION_MSG(" V4Transmit.IpChecksum = %d\n", nttic->V4Transmit.IpChecksum);
445 FUNCTION_MSG(" V4Receive.IpOptionsSupported = %d\n", nttic->V4Receive.IpOptionsSupported);
446 FUNCTION_MSG(" V4Receive.TcpOptionsSupported = %d\n", nttic->V4Receive.TcpOptionsSupported);
447 FUNCTION_MSG(" V4Receive.TcpChecksum = %d\n", nttic->V4Receive.TcpChecksum);
448 FUNCTION_MSG(" V4Receive.UdpChecksum = %d\n", nttic->V4Receive.UdpChecksum);
449 FUNCTION_MSG(" V4Receive.IpChecksum = %d\n", nttic->V4Receive.IpChecksum);
450 FUNCTION_MSG(" V6Transmit.IpOptionsSupported = %d\n", nttic->V6Transmit.IpOptionsSupported);
451 FUNCTION_MSG(" V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported);
452 FUNCTION_MSG(" V6Transmit.TcpChecksum = %d\n", nttic->V6Transmit.TcpChecksum);
453 FUNCTION_MSG(" V6Transmit.UdpChecksum = %d\n", nttic->V6Transmit.UdpChecksum);
454 FUNCTION_MSG(" V6Receive.IpOptionsSupported = %d\n", nttic->V6Receive.IpOptionsSupported);
455 FUNCTION_MSG(" V6Receive.TcpOptionsSupported = %d\n", nttic->V6Receive.TcpOptionsSupported);
456 FUNCTION_MSG(" V6Receive.TcpChecksum = %d\n", nttic->V6Receive.TcpChecksum);
457 FUNCTION_MSG(" V6Receive.UdpChecksum = %d\n", nttic->V6Receive.UdpChecksum);
458 /* check for stuff we outright don't support */
459 if (nttic->V6Transmit.IpOptionsSupported ||
460 nttic->V6Transmit.TcpOptionsSupported ||
461 nttic->V6Transmit.TcpChecksum ||
462 nttic->V6Transmit.UdpChecksum ||
463 nttic->V6Receive.IpOptionsSupported ||
464 nttic->V6Receive.TcpOptionsSupported ||
465 nttic->V6Receive.TcpChecksum ||
466 nttic->V6Receive.UdpChecksum) {
467 FUNCTION_MSG("IPv6 offload not supported\n");
468 return NDIS_STATUS_INVALID_DATA;
469 }
470 if (nttic->V4Transmit.IpOptionsSupported || nttic->V4Transmit.IpChecksum) {
471 FUNCTION_MSG("IPv4 IP Transmit offload not supported\n");
472 return NDIS_STATUS_INVALID_DATA;
473 }
474 if (nttic->V4Receive.IpOptionsSupported && !nttic->V4Receive.IpChecksum) {
475 FUNCTION_MSG("Invalid combination\n");
476 return NDIS_STATUS_INVALID_DATA;
477 }
478 if (nttic->V4Transmit.TcpOptionsSupported && !nttic->V4Transmit.TcpChecksum) {
479 FUNCTION_MSG("Invalid combination\n");
480 return NDIS_STATUS_INVALID_DATA;
481 }
482 if (nttic->V4Receive.TcpOptionsSupported && !nttic->V4Receive.TcpChecksum) {
483 FUNCTION_MSG("Invalid combination\n");
484 return NDIS_STATUS_INVALID_DATA;
485 }
486 break;
487 case TcpLargeSendNdisTask:
488 *bytes_read += sizeof(NDIS_TASK_TCP_LARGE_SEND);
489 FUNCTION_MSG("TcpLargeSendNdisTask\n");
490 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
491 FUNCTION_MSG(" MaxOffLoadSize = %d\n", nttls->MaxOffLoadSize);
492 FUNCTION_MSG(" MinSegmentCount = %d\n", nttls->MinSegmentCount);
493 FUNCTION_MSG(" TcpOptions = %d\n", nttls->TcpOptions);
494 FUNCTION_MSG(" IpOptions = %d\n", nttls->IpOptions);
495 if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS) {
496 FUNCTION_MSG("MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS);
497 return NDIS_STATUS_INVALID_DATA;
498 }
499 if (nttls->IpOptions) {
500 FUNCTION_MSG("IpOptions not supported\n");
501 return NDIS_STATUS_INVALID_DATA;
502 }
503 if (nttls->TcpOptions) {
504 FUNCTION_MSG("TcpOptions not supported\n");
505 return NDIS_STATUS_INVALID_DATA;
506 }
507 break;
508 default:
509 FUNCTION_MSG("Unknown Task %d\n", nto->Task);
510 }
511 offset = nto->OffsetNextTask;
512 }
513 if (nttic != NULL) {
514 xi->current_csum_supported = TRUE;
515 xi->setting_csum = *nttic;
516 } else {
517 RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
518 FUNCTION_MSG("csum offload disabled\n", nto->Task);
519 }
520 if (nttls != NULL)
521 xi->current_gso_value = nttls->MaxOffLoadSize;
522 else {
523 xi->current_gso_value = 0;
524 FUNCTION_MSG("LSO disabled\n", nto->Task);
525 }
526 return STATUS_SUCCESS;
527 }
528 #else
529 NDIS_STATUS
530 XenNet_QueryOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
531 PNDIS_INTERRUPT_MODERATION_PARAMETERS nimp;
532 UNREFERENCED_PARAMETER(context);
533 UNREFERENCED_PARAMETER(bytes_needed);
534 UNREFERENCED_PARAMETER(information_buffer_length);
535 nimp = (PNDIS_INTERRUPT_MODERATION_PARAMETERS)information_buffer;
536 nimp->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
537 nimp->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
538 nimp->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
539 nimp->Flags = 0;
540 nimp->InterruptModeration = NdisInterruptModerationNotSupported;
541 *bytes_written = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
542 return STATUS_SUCCESS;
543 }
545 NDIS_STATUS
546 XenNet_SetOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
547 UNREFERENCED_PARAMETER(context);
548 UNREFERENCED_PARAMETER(information_buffer);
549 UNREFERENCED_PARAMETER(information_buffer_length);
550 UNREFERENCED_PARAMETER(bytes_read);
551 UNREFERENCED_PARAMETER(bytes_needed);
552 return STATUS_NOT_SUPPORTED;
553 }
555 NDIS_STATUS
556 XenNet_QueryOID_GEN_STATISTICS(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) {
557 struct xennet_info *xi = context;
558 UNREFERENCED_PARAMETER(bytes_needed);
559 UNREFERENCED_PARAMETER(information_buffer_length);
561 NdisMoveMemory(information_buffer, &xi->stats, sizeof(NDIS_STATISTICS_INFO));
562 *bytes_written = sizeof(NDIS_STATISTICS_INFO);
563 return STATUS_SUCCESS;
564 }
566 NDIS_STATUS
567 XenNet_SetOID_OFFLOAD_ENCAPSULATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
568 struct xennet_info *xi = context;
569 PNDIS_OFFLOAD_ENCAPSULATION noe = (PNDIS_OFFLOAD_ENCAPSULATION)information_buffer;
570 UNREFERENCED_PARAMETER(bytes_needed);
571 UNREFERENCED_PARAMETER(information_buffer_length);
572 /* mostly assume that NDIS vets the settings for us */
573 if (noe->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3) {
574 FUNCTION_MSG("Unknown Encapsulation Type %d\n", noe->IPv4.EncapsulationType);
575 return NDIS_STATUS_NOT_SUPPORTED;
576 }
578 switch(noe->IPv4.Enabled) {
579 case NDIS_OFFLOAD_SET_ON:
580 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_ON\n");
581 xi->current_csum_supported = xi->backend_csum_supported && xi->frontend_csum_supported;
582 xi->current_gso_value = min(xi->backend_csum_supported, xi->frontend_csum_supported);
583 break;
584 case NDIS_OFFLOAD_SET_OFF:
585 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_OFF\n");
586 xi->current_csum_supported = FALSE;
587 xi->current_gso_value = 0;
588 break;
589 case NDIS_OFFLOAD_SET_NO_CHANGE:
590 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
591 break;
592 }
593 FUNCTION_MSG(" IPv4.HeaderSize = %d\n", noe->IPv4.HeaderSize);
594 FUNCTION_MSG(" IPv6.EncapsulationType = %d\n", noe->IPv6.EncapsulationType);
595 switch(noe->IPv6.Enabled) {
596 case NDIS_OFFLOAD_SET_ON:
597 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_ON (this is an error)\n");
598 break;
599 case NDIS_OFFLOAD_SET_OFF:
600 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_OFF\n");
601 break;
602 case NDIS_OFFLOAD_SET_NO_CHANGE:
603 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
604 break;
605 }
606 *bytes_read = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
607 FUNCTION_MSG(" IPv6.HeaderSize = %d\n", noe->IPv6.HeaderSize);
608 return NDIS_STATUS_SUCCESS;
609 }
610 #endif
612 NDIS_STATUS
613 XenNet_SetOID_PNP_SET_POWER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
614 UNREFERENCED_PARAMETER(context);
615 UNREFERENCED_PARAMETER(information_buffer);
616 UNREFERENCED_PARAMETER(information_buffer_length);
617 UNREFERENCED_PARAMETER(bytes_read);
618 UNREFERENCED_PARAMETER(bytes_needed);
619 return STATUS_NOT_SUPPORTED;
620 }
622 NDIS_STATUS
623 XenNet_SetOID_GEN_NETWORK_LAYER_ADDRESSES(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
624 PNETWORK_ADDRESS_LIST nal = information_buffer;
625 PNETWORK_ADDRESS na;
626 PNETWORK_ADDRESS_IP ip;
627 int i;
629 UNREFERENCED_PARAMETER(context);
630 UNREFERENCED_PARAMETER(bytes_read);
631 UNREFERENCED_PARAMETER(bytes_needed);
632 FUNCTION_MSG("AddressType = %d\n", nal->AddressType);
633 FUNCTION_MSG("AddressCount = %d\n", nal->AddressCount);
634 if (nal->AddressCount == 0) {
635 // remove addresses of AddressType type
636 } else {
637 na = nal->Address;
638 for (i = 0; i < nal->AddressCount; i++) {
639 if ((ULONG_PTR)na - (ULONG_PTR)nal + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength > information_buffer_length) {
640 FUNCTION_MSG("Out of bounds\n");
641 return NDIS_STATUS_INVALID_DATA;
642 }
643 switch(na->AddressType) {
644 case NDIS_PROTOCOL_ID_TCP_IP:
645 FUNCTION_MSG("Address[%d].Type = NDIS_PROTOCOL_ID_TCP_IP\n", i);
646 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
647 if (na->AddressLength != NETWORK_ADDRESS_LENGTH_IP) {
648 FUNCTION_MSG("Length is invalid\n");
649 break;
650 }
651 ip = (PNETWORK_ADDRESS_IP)na->Address;
652 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);
653 break;
654 default:
655 FUNCTION_MSG("Address[%d].Type = %d\n", i, na->AddressType);
656 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
657 break;
658 }
659 na = (PNETWORK_ADDRESS)((PUCHAR)na + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength);
660 }
661 }
663 return NDIS_STATUS_SUCCESS;
664 }
666 NDIS_STATUS
667 XenNet_SetOID_GEN_MACHINE_NAME(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) {
668 UNICODE_STRING name;
669 UNREFERENCED_PARAMETER(context);
670 UNREFERENCED_PARAMETER(bytes_read);
671 UNREFERENCED_PARAMETER(bytes_needed);
673 name.Length = (USHORT)information_buffer_length;
674 name.MaximumLength = (USHORT)information_buffer_length;
675 name.Buffer = information_buffer;
676 FUNCTION_MSG("name = %wZ\n", &name);
677 return NDIS_STATUS_SUCCESS;
678 }
680 struct xennet_oids_t xennet_oids[] = {
681 DEF_OID_QUERY_ULONG(OID_GEN_HARDWARE_STATUS),
683 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BUFFER_SPACE),
684 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BUFFER_SPACE),
685 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BLOCK_SIZE),
686 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BLOCK_SIZE),
688 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_ID),
689 DEF_OID_QUERY(OID_GEN_VENDOR_DESCRIPTION, sizeof(XN_VENDOR_DESC)),
690 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_DRIVER_VERSION),
692 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_PACKET_FILTER),
693 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_LOOKAHEAD),
694 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_TOTAL_SIZE),
696 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_SEND_PACKETS),
697 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_SUPPORTED),
698 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_IN_USE),
699 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_LOOKAHEAD),
701 /* general optional */
702 DEF_OID_SET(OID_GEN_NETWORK_LAYER_ADDRESSES, FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)),
703 DEF_OID_SET(OID_GEN_MACHINE_NAME, 0),
705 /* power */
706 DEF_OID_SET_ULONG(OID_PNP_SET_POWER),
708 /* stats */
709 DEF_OID_QUERY_STAT(OID_GEN_XMIT_OK),
710 DEF_OID_QUERY_STAT(OID_GEN_RCV_OK),
711 DEF_OID_QUERY_STAT(OID_GEN_XMIT_ERROR),
712 DEF_OID_QUERY_STAT(OID_GEN_RCV_ERROR),
713 DEF_OID_QUERY_STAT(OID_GEN_RCV_NO_BUFFER),
714 DEF_OID_QUERY_STAT(OID_802_3_RCV_ERROR_ALIGNMENT),
715 DEF_OID_QUERY_STAT(OID_802_3_XMIT_ONE_COLLISION),
716 DEF_OID_QUERY_STAT(OID_802_3_XMIT_MORE_COLLISIONS),
717 DEF_OID_NONE(OID_IP4_OFFLOAD_STATS),
718 DEF_OID_NONE(OID_IP6_OFFLOAD_STATS),
720 /* media-specific */
721 DEF_OID_QUERY(OID_802_3_PERMANENT_ADDRESS, 6),
722 DEF_OID_QUERY(OID_802_3_CURRENT_ADDRESS, 6),
723 DEF_OID_QUERYSET(OID_802_3_MULTICAST_LIST, 0),
724 DEF_OID_QUERY_ULONG(OID_802_3_MAXIMUM_LIST_SIZE),
726 #if NTDDI_VERSION < NTDDI_VISTA
727 DEF_OID_QUERY(OID_GEN_SUPPORTED_LIST, 0),
728 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_FRAME_SIZE),
729 DEF_OID_QUERY_ULONG(OID_GEN_LINK_SPEED),
730 DEF_OID_QUERY(OID_GEN_DRIVER_VERSION, sizeof(USHORT)),
731 DEF_OID_QUERY_ULONG(OID_GEN_MAC_OPTIONS),
732 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_CONNECT_STATUS),
733 DEF_OID_QUERYSET(OID_TCP_TASK_OFFLOAD, 0),
734 DEF_OID_QUERY(OID_PNP_CAPABILITIES, sizeof(NDIS_PNP_CAPABILITIES)),
735 DEF_OID_QUERY(OID_PNP_QUERY_POWER, 0),
736 DEF_OID_SET(OID_GEN_PROTOCOL_OPTIONS, 0),
737 #else
738 DEF_OID_SET(OID_GEN_LINK_PARAMETERS, sizeof(NDIS_LINK_PARAMETERS)),
739 DEF_OID_QUERYSET(OID_GEN_INTERRUPT_MODERATION, sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS)),
740 DEF_OID_SET(OID_OFFLOAD_ENCAPSULATION, sizeof(NDIS_OFFLOAD_ENCAPSULATION)),
741 DEF_OID_QUERY(OID_GEN_STATISTICS, sizeof(NDIS_STATISTICS_INFO)),
742 #endif
743 {0, "", 0, NULL, NULL}
744 };
746 //static NDIS_OID supported_oids[ARRAY_SIZE(xennet_oids)];
747 #if NTDDI_VERSION < NTDDI_VISTA
748 NDIS_STATUS
749 XenNet_SetInformation(
750 NDIS_HANDLE adapter_context,
751 NDIS_OID oid,
752 PVOID information_buffer,
753 ULONG information_buffer_length,
754 PULONG bytes_read,
755 PULONG bytes_needed) {
756 NTSTATUS status;
757 int i;
759 FUNCTION_ENTER();
760 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
762 if (!xennet_oids[i].oid) {
763 FUNCTION_MSG("Unsupported OID %08x\n", oid);
764 return NDIS_STATUS_NOT_SUPPORTED;
765 }
766 if (information_buffer_length < xennet_oids[i].min_length) {
767 FUNCTION_MSG("%s Set InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length);
768 *bytes_needed = xennet_oids[i].min_length;
769 return NDIS_STATUS_BUFFER_TOO_SHORT;
770 }
771 if (!xennet_oids[i].set_routine) {
772 FUNCTION_MSG("%s Set not supported\n", xennet_oids[i].oid_name);
773 return NDIS_STATUS_NOT_SUPPORTED;
774 }
775 FUNCTION_MSG("%s\n", xennet_oids[i].oid_name);
776 status = xennet_oids[i].set_routine(adapter_context, information_buffer, information_buffer_length, bytes_read, bytes_needed);
777 FUNCTION_EXIT();
778 return status;
779 }
781 NDIS_STATUS
782 XenNet_QueryInformation(
783 IN NDIS_HANDLE adapter_context,
784 IN NDIS_OID oid,
785 IN PVOID information_buffer,
786 IN ULONG information_buffer_length,
787 OUT PULONG bytes_written,
788 OUT PULONG bytes_needed) {
789 NTSTATUS status;
790 int i;
792 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
794 if (!xennet_oids[i].oid) {
795 FUNCTION_MSG("Unsupported OID %08x\n", oid);
796 return NDIS_STATUS_NOT_SUPPORTED;
797 }
798 if (information_buffer_length < xennet_oids[i].min_length) {
799 FUNCTION_MSG("%s Query InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length);
800 *bytes_needed = xennet_oids[i].min_length;
801 return NDIS_STATUS_BUFFER_TOO_SHORT;
802 }
803 if (!xennet_oids[i].query_routine) {
804 FUNCTION_MSG("%s Query not supported\n", xennet_oids[i].oid_name);
805 return NDIS_STATUS_NOT_SUPPORTED;
806 }
807 //FUNCTION_MSG("%s\n", xennet_oids[i].oid_name);
808 status = xennet_oids[i].query_routine(adapter_context, information_buffer, information_buffer_length, bytes_written, bytes_needed);
809 return status;
810 }
812 #else
813 NDIS_STATUS
814 XenNet_OidRequest(NDIS_HANDLE adapter_context, PNDIS_OID_REQUEST oid_request)
815 {
816 NTSTATUS status;
817 int i;
818 NDIS_OID oid;
820 //FUNCTION_ENTER();
821 switch(oid_request->RequestType)
822 {
823 case NdisRequestQueryInformation:
824 //FUNCTION_MSG("RequestType = NdisRequestQueryInformation\n");
825 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
826 break;
827 case NdisRequestSetInformation:
828 //FUNCTION_MSG("RequestType = NdisRequestSetInformation\n");
829 oid = oid_request->DATA.SET_INFORMATION.Oid;
830 break;
831 case NdisRequestQueryStatistics:
832 //FUNCTION_MSG("RequestType = NdisRequestQueryStatistics\n");
833 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
834 break;
835 default:
836 //FUNCTION_MSG("RequestType = NdisRequestQuery%d\n", oid_request->RequestType);
837 return NDIS_STATUS_NOT_SUPPORTED;
838 }
839 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
841 if (!xennet_oids[i].oid) {
842 FUNCTION_MSG("Unsupported OID %08x\n", oid);
843 return NDIS_STATUS_NOT_SUPPORTED;
844 }
845 //FUNCTION_MSG("Oid = %s\n", xennet_oids[i].oid_name);
846 switch(oid_request->RequestType)
847 {
848 case NdisRequestQueryInformation:
849 case NdisRequestQueryStatistics:
850 if (oid_request->DATA.QUERY_INFORMATION.InformationBufferLength < xennet_oids[i].min_length) {
851 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.QUERY_INFORMATION.InformationBufferLength, xennet_oids[i].min_length);
852 oid_request->DATA.QUERY_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
853 return NDIS_STATUS_BUFFER_TOO_SHORT;
854 }
855 if (!xennet_oids[i].query_routine) {
856 //FUNCTION_MSG("Operation not supported\n");
857 return NDIS_STATUS_NOT_SUPPORTED;
858 }
859 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);
860 break;
861 case NdisRequestSetInformation:
862 if (oid_request->DATA.SET_INFORMATION.InformationBufferLength < xennet_oids[i].min_length) {
863 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.SET_INFORMATION.InformationBufferLength, xennet_oids[i].min_length);
864 oid_request->DATA.SET_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
865 return NDIS_STATUS_BUFFER_TOO_SHORT;
866 }
867 if (!xennet_oids[i].set_routine) {
868 //FUNCTION_MSG("Operation not supported\n");
869 return NDIS_STATUS_NOT_SUPPORTED;
870 }
871 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);
872 break;
873 default:
874 return NDIS_STATUS_NOT_SUPPORTED;
875 }
876 //FUNCTION_EXIT();
877 return status;
878 }
880 VOID
881 XenNet_CancelOidRequest(NDIS_HANDLE adapter_context, PVOID request_id)
882 {
883 UNREFERENCED_PARAMETER(adapter_context);
884 UNREFERENCED_PARAMETER(request_id);
885 FUNCTION_ENTER();
886 FUNCTION_EXIT();
887 }
888 #endif