win-pvdrivers

view xennet/xennet6_oid.c @ 1001:c21dd04d3ae6

Less noise for xennet6
author James Harper <james.harper@bendigoit.com.au>
date Fri Dec 14 21:26:22 2012 +1100 (2012-12-14)
parents e16e389a3cb5
children 4f7d5a8636bd
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 "xennet6.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, PNDIS_OID_REQUEST request) \
36 { \
37 struct xennet_info *xi = context; \
38 UNREFERENCED_PARAMETER(xi); \
39 if (request->DATA.QUERY_INFORMATION.InformationBufferLength < length) \
40 { \
41 request->DATA.QUERY_INFORMATION.BytesNeeded = length; \
42 return NDIS_STATUS_BUFFER_TOO_SHORT; \
43 } \
44 request->DATA.QUERY_INFORMATION.BytesWritten = length; \
45 NdisMoveMemory(request->DATA.QUERY_INFORMATION.InformationBuffer, value, length); \
46 return STATUS_SUCCESS; \
47 }
49 #define DEF_OID_QUERY_ULONG_ROUTINE(oid, value) \
50 NDIS_STATUS \
51 XenNet_Query##oid(NDIS_HANDLE context, PNDIS_OID_REQUEST request) \
52 { \
53 struct xennet_info *xi = context; \
54 UNREFERENCED_PARAMETER(xi); \
55 request->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG); \
56 *(ULONG *)request->DATA.QUERY_INFORMATION.InformationBuffer = 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, PNDIS_OID_REQUEST request) \
63 { \
64 struct xennet_info *xi = context; \
65 UNREFERENCED_PARAMETER(xi); \
66 if (request->DATA.QUERY_INFORMATION.InformationBufferLength >= 8) \
67 { \
68 request->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG64); \
69 *(ULONG64 *)request->DATA.QUERY_INFORMATION.InformationBuffer = (value); \
70 } \
71 else if (request->DATA.QUERY_INFORMATION.InformationBufferLength >= 4) \
72 { \
73 request->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG); \
74 request->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); \
75 *(ULONG *)request->DATA.QUERY_INFORMATION.InformationBuffer = (ULONG)(value); \
76 } \
77 else \
78 { \
79 request->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); \
80 return NDIS_STATUS_BUFFER_TOO_SHORT; \
81 } \
82 return STATUS_SUCCESS; \
83 }
85 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_TOTAL_SIZE, xi->current_mtu_value + XN_HDR_SIZE)
86 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_PACKET_FILTER, xi->packet_filter)
87 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_CURRENT_LOOKAHEAD, xi->current_lookahead)
88 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BUFFER_SPACE, PAGE_SIZE * NET_TX_RING_SIZE * 4)
89 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BUFFER_SPACE, PAGE_SIZE * NET_RX_RING_SIZE * 2)
90 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_TRANSMIT_BLOCK_SIZE, PAGE_SIZE)
91 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_RECEIVE_BLOCK_SIZE, PAGE_SIZE)
92 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_SEND_PACKETS, 0)
93 DEF_OID_QUERY_ULONG_ROUTINE(OID_802_3_MAXIMUM_LIST_SIZE, MULTICAST_LIST_MAX_SIZE)
94 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_HARDWARE_STATUS, xi->connected?NdisHardwareStatusReady:NdisHardwareStatusInitializing)
95 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_ID, 0xFFFFFF) // Not guaranteed to be XENSOURCE_MAC_HDR;
96 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_VENDOR_DRIVER_VERSION, VENDOR_DRIVER_VERSION)
97 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_SUPPORTED, NdisMedium802_3)
98 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MEDIA_IN_USE, NdisMedium802_3)
99 DEF_OID_QUERY_ULONG_ROUTINE(OID_GEN_MAXIMUM_LOOKAHEAD, MAX_LOOKAHEAD_LENGTH)
101 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_OK, xi->stats.ifHCOutUcastPkts + xi->stats.ifHCOutMulticastPkts + xi->stats.ifHCOutBroadcastPkts)
102 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_XMIT_ERROR, xi->stats.ifOutErrors)
103 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_OK, xi->stats.ifHCInUcastPkts + xi->stats.ifHCInMulticastPkts + xi->stats.ifHCInBroadcastPkts)
104 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_ERROR, xi->stats.ifInErrors)
105 DEF_OID_QUERY_STAT_ROUTINE(OID_GEN_RCV_NO_BUFFER, xi->stats.ifInDiscards)
106 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_RCV_ERROR_ALIGNMENT, 0)
107 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_ONE_COLLISION, 0)
108 DEF_OID_QUERY_STAT_ROUTINE(OID_802_3_XMIT_MORE_COLLISIONS, 0)
110 DEF_OID_QUERY_ROUTINE(OID_GEN_VENDOR_DESCRIPTION, XN_VENDOR_DESC, sizeof(XN_VENDOR_DESC))
112 DEF_OID_QUERY_ROUTINE(OID_802_3_PERMANENT_ADDRESS, xi->perm_mac_addr, ETH_ALEN)
113 DEF_OID_QUERY_ROUTINE(OID_802_3_CURRENT_ADDRESS, xi->curr_mac_addr, ETH_ALEN)
115 DEF_OID_QUERY_ROUTINE(OID_802_3_MULTICAST_LIST, xi->multicast_list, xi->multicast_list_size * 6)
117 NDIS_STATUS
118 XenNet_SetOID_802_3_MULTICAST_LIST(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
119 {
120 struct xennet_info *xi = context;
121 UCHAR *multicast_list;
122 int i;
124 if (request->DATA.SET_INFORMATION.InformationBufferLength > MULTICAST_LIST_MAX_SIZE * 6)
125 {
126 return NDIS_STATUS_MULTICAST_FULL;
127 }
129 if (request->DATA.SET_INFORMATION.InformationBufferLength % 6 != 0)
130 {
131 return NDIS_STATUS_MULTICAST_FULL;
132 }
133 multicast_list = request->DATA.SET_INFORMATION.InformationBuffer;
134 for (i = 0; i < (int)request->DATA.SET_INFORMATION.InformationBufferLength / 6; i++)
135 {
136 if (!(multicast_list[i * 6 + 0] & 0x01))
137 {
138 FUNCTION_MSG("Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i,
139 (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1],
140 (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3],
141 (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]);
142 /* 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... */
143 }
144 }
145 memcpy(xi->multicast_list, multicast_list, request->DATA.SET_INFORMATION.InformationBufferLength);
146 xi->multicast_list_size = request->DATA.SET_INFORMATION.InformationBufferLength / 6;
147 return NDIS_STATUS_SUCCESS;
148 }
150 NDIS_STATUS
151 XenNet_SetOID_GEN_CURRENT_PACKET_FILTER(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
152 {
153 struct xennet_info *xi = context;
154 PULONG data = request->DATA.SET_INFORMATION.InformationBuffer;
156 request->DATA.SET_INFORMATION.BytesNeeded = sizeof(ULONG64);
157 if (*data & NDIS_PACKET_TYPE_DIRECTED)
158 FUNCTION_MSG("NDIS_PACKET_TYPE_DIRECTED\n");
159 if (*data & NDIS_PACKET_TYPE_MULTICAST)
160 FUNCTION_MSG("NDIS_PACKET_TYPE_MULTICAST\n");
161 if (*data & NDIS_PACKET_TYPE_ALL_MULTICAST)
162 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_MULTICAST\n");
163 if (*data & NDIS_PACKET_TYPE_BROADCAST)
164 FUNCTION_MSG("NDIS_PACKET_TYPE_BROADCAST\n");
165 if (*data & NDIS_PACKET_TYPE_PROMISCUOUS)
166 FUNCTION_MSG("NDIS_PACKET_TYPE_PROMISCUOUS\n");
167 if (*data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
168 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n");
169 if (*data & NDIS_PACKET_TYPE_ALL_LOCAL)
170 FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n");
171 if (*data & NDIS_PACKET_TYPE_FUNCTIONAL)
172 FUNCTION_MSG("NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n");
173 if (*data & NDIS_PACKET_TYPE_GROUP)
174 FUNCTION_MSG("NDIS_PACKET_TYPE_GROUP (not supported)\n");
175 if (*data & ~SUPPORTED_PACKET_FILTERS)
176 {
177 FUNCTION_MSG("returning NDIS_STATUS_NOT_SUPPORTED\n");
178 return NDIS_STATUS_NOT_SUPPORTED;
179 }
180 xi->packet_filter = *(ULONG *)data;
181 request->DATA.SET_INFORMATION.BytesRead = sizeof(ULONG);
182 return NDIS_STATUS_SUCCESS;
183 }
185 NDIS_STATUS
186 XenNet_SetOID_GEN_CURRENT_LOOKAHEAD(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
187 {
188 struct xennet_info *xi = context;
189 PULONG data = request->DATA.QUERY_INFORMATION.InformationBuffer;
190 xi->current_lookahead = *(ULONG *)data;
191 FUNCTION_MSG("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi);
192 return NDIS_STATUS_SUCCESS;
193 }
195 NDIS_STATUS
196 XenNet_SetOID_GEN_LINK_PARAMETERS(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
197 {
198 UNREFERENCED_PARAMETER(context);
199 UNREFERENCED_PARAMETER(request);
200 return STATUS_NOT_SUPPORTED;
201 }
203 NDIS_STATUS
204 XenNet_QueryOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
205 {
206 PNDIS_INTERRUPT_MODERATION_PARAMETERS nimp;
207 UNREFERENCED_PARAMETER(context);
208 nimp = (PNDIS_INTERRUPT_MODERATION_PARAMETERS)request->DATA.QUERY_INFORMATION.InformationBuffer;
209 nimp->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
210 nimp->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
211 nimp->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
212 nimp->Flags = 0;
213 nimp->InterruptModeration = NdisInterruptModerationNotSupported;
214 request->DATA.SET_INFORMATION.BytesRead = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
215 return STATUS_SUCCESS;
216 }
218 NDIS_STATUS
219 XenNet_SetOID_GEN_INTERRUPT_MODERATION(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
220 {
221 UNREFERENCED_PARAMETER(context);
222 UNREFERENCED_PARAMETER(request);
223 return STATUS_NOT_SUPPORTED;
224 }
226 NDIS_STATUS
227 XenNet_QueryOID_GEN_STATISTICS(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
228 {
229 struct xennet_info *xi = context;
231 NdisMoveMemory(request->DATA.QUERY_INFORMATION.InformationBuffer, &xi->stats, sizeof(NDIS_STATISTICS_INFO));
232 request->DATA.SET_INFORMATION.BytesRead = sizeof(NDIS_STATISTICS_INFO);
233 return STATUS_SUCCESS;
234 }
236 NDIS_STATUS
237 XenNet_SetOID_PNP_SET_POWER(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
238 {
239 UNREFERENCED_PARAMETER(context);
240 UNREFERENCED_PARAMETER(request);
241 return STATUS_NOT_SUPPORTED;
242 }
244 NDIS_STATUS
245 XenNet_SetOID_GEN_NETWORK_LAYER_ADDRESSES(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
246 {
247 PNETWORK_ADDRESS_LIST nal = request->DATA.QUERY_INFORMATION.InformationBuffer;
248 PNETWORK_ADDRESS na;
249 PNETWORK_ADDRESS_IP ip;
250 int i;
252 UNREFERENCED_PARAMETER(context);
253 FUNCTION_MSG("AddressType = %d\n", nal->AddressType);
254 FUNCTION_MSG("AddressCount = %d\n", nal->AddressCount);
255 if (nal->AddressCount == 0)
256 {
257 // remove addresses of AddressType type
258 }
259 else
260 {
261 na = nal->Address;
262 for (i = 0; i < nal->AddressCount; i++)
263 {
264 if ((ULONG_PTR)na - (ULONG_PTR)nal + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength > request->DATA.QUERY_INFORMATION.InformationBufferLength)
265 {
266 FUNCTION_MSG("Out of bounds\n");
267 return NDIS_STATUS_INVALID_DATA;
268 }
269 switch(na->AddressType)
270 {
271 case NDIS_PROTOCOL_ID_TCP_IP:
272 FUNCTION_MSG("Address[%d].Type = NDIS_PROTOCOL_ID_TCP_IP\n", i);
273 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
274 if (na->AddressLength != NETWORK_ADDRESS_LENGTH_IP)
275 {
276 FUNCTION_MSG("Length is invalid\n");
277 break;
278 }
279 ip = (PNETWORK_ADDRESS_IP)na->Address;
280 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);
281 break;
282 default:
283 FUNCTION_MSG("Address[%d].Type = %d\n", i, na->AddressType);
284 FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength);
285 break;
286 }
287 na = (PNETWORK_ADDRESS)((PUCHAR)na + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength);
288 }
289 }
291 return NDIS_STATUS_SUCCESS;
292 }
294 NDIS_STATUS
295 XenNet_SetOID_GEN_MACHINE_NAME(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
296 {
297 UNICODE_STRING name;
298 UNREFERENCED_PARAMETER(context);
300 name.Length = (USHORT)request->DATA.QUERY_INFORMATION.InformationBufferLength;
301 name.MaximumLength = (USHORT)request->DATA.QUERY_INFORMATION.InformationBufferLength;
302 name.Buffer = request->DATA.QUERY_INFORMATION.InformationBuffer;
303 FUNCTION_MSG("name = %wZ\n", &name);
304 return NDIS_STATUS_SUCCESS;
305 }
307 NDIS_STATUS
308 XenNet_SetOID_OFFLOAD_ENCAPSULATION(NDIS_HANDLE context, PNDIS_OID_REQUEST request)
309 {
310 struct xennet_info *xi = context;
311 /* mostly assume that NDIS vets the settings for us */
312 PNDIS_OFFLOAD_ENCAPSULATION noe = (PNDIS_OFFLOAD_ENCAPSULATION)request->DATA.SET_INFORMATION.InformationBuffer;
313 if (noe->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
314 {
315 FUNCTION_MSG("Unknown Encapsulation Type %d\n", noe->IPv4.EncapsulationType);
316 return NDIS_STATUS_NOT_SUPPORTED;
317 }
319 switch(noe->IPv4.Enabled)
320 {
321 case NDIS_OFFLOAD_SET_ON:
322 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_ON\n");
323 xi->current_csum_supported = xi->backend_csum_supported && xi->frontend_csum_supported;
324 xi->current_gso_value = min(xi->backend_csum_supported, xi->frontend_csum_supported);
325 break;
326 case NDIS_OFFLOAD_SET_OFF:
327 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_OFF\n");
328 xi->current_csum_supported = FALSE;
329 xi->current_gso_value = 0;
330 break;
331 case NDIS_OFFLOAD_SET_NO_CHANGE:
332 FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
333 break;
334 }
335 FUNCTION_MSG(" IPv4.HeaderSize = %d\n", noe->IPv4.HeaderSize);
336 FUNCTION_MSG(" IPv6.EncapsulationType = %d\n", noe->IPv6.EncapsulationType);
337 switch(noe->IPv6.Enabled)
338 {
339 case NDIS_OFFLOAD_SET_ON:
340 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_ON (this is an error)\n");
341 break;
342 case NDIS_OFFLOAD_SET_OFF:
343 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_OFF\n");
344 break;
345 case NDIS_OFFLOAD_SET_NO_CHANGE:
346 FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_NO_CHANGE\n");
347 break;
348 }
349 FUNCTION_MSG(" IPv6.HeaderSize = %d\n", noe->IPv6.HeaderSize);
350 return NDIS_STATUS_SUCCESS;
351 }
353 struct xennet_oids_t xennet_oids[] = {
354 DEF_OID_QUERY_ULONG(OID_GEN_HARDWARE_STATUS),
356 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BUFFER_SPACE),
357 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BUFFER_SPACE),
358 DEF_OID_QUERY_ULONG(OID_GEN_TRANSMIT_BLOCK_SIZE),
359 DEF_OID_QUERY_ULONG(OID_GEN_RECEIVE_BLOCK_SIZE),
361 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_ID),
362 DEF_OID_QUERY(OID_GEN_VENDOR_DESCRIPTION, sizeof(XN_VENDOR_DESC)),
363 DEF_OID_QUERY_ULONG(OID_GEN_VENDOR_DRIVER_VERSION),
365 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_PACKET_FILTER),
366 DEF_OID_QUERYSET_ULONG(OID_GEN_CURRENT_LOOKAHEAD),
367 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_TOTAL_SIZE),
368 DEF_OID_SET(OID_GEN_LINK_PARAMETERS, sizeof(NDIS_LINK_PARAMETERS)),
369 DEF_OID_QUERYSET(OID_GEN_INTERRUPT_MODERATION, sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS)),
371 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_SEND_PACKETS),
372 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_SUPPORTED),
373 DEF_OID_QUERY_ULONG(OID_GEN_MEDIA_IN_USE),
374 DEF_OID_QUERY_ULONG(OID_GEN_MAXIMUM_LOOKAHEAD),
376 /* general optional */
377 DEF_OID_SET(OID_GEN_NETWORK_LAYER_ADDRESSES, FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address)),
378 DEF_OID_SET(OID_GEN_MACHINE_NAME, 0),
379 DEF_OID_SET(OID_OFFLOAD_ENCAPSULATION, sizeof(NDIS_OFFLOAD_ENCAPSULATION)),
381 /* power */
382 DEF_OID_SET_ULONG(OID_PNP_SET_POWER),
384 /* stats */
385 DEF_OID_QUERY_STAT(OID_GEN_XMIT_OK),
386 DEF_OID_QUERY_STAT(OID_GEN_RCV_OK),
387 DEF_OID_QUERY_STAT(OID_GEN_XMIT_ERROR),
388 DEF_OID_QUERY_STAT(OID_GEN_RCV_ERROR),
389 DEF_OID_QUERY_STAT(OID_GEN_RCV_NO_BUFFER),
390 DEF_OID_QUERY_STAT(OID_802_3_RCV_ERROR_ALIGNMENT),
391 DEF_OID_QUERY_STAT(OID_802_3_XMIT_ONE_COLLISION),
392 DEF_OID_QUERY_STAT(OID_802_3_XMIT_MORE_COLLISIONS),
393 DEF_OID_NONE(OID_IP4_OFFLOAD_STATS),
394 DEF_OID_NONE(OID_IP6_OFFLOAD_STATS),
395 DEF_OID_QUERY(OID_GEN_STATISTICS, sizeof(NDIS_STATISTICS_INFO)),
397 /* media-specific */
398 DEF_OID_QUERY(OID_802_3_PERMANENT_ADDRESS, 6),
399 DEF_OID_QUERY(OID_802_3_CURRENT_ADDRESS, 6),
400 DEF_OID_QUERYSET(OID_802_3_MULTICAST_LIST, 0),
401 DEF_OID_QUERY_ULONG(OID_802_3_MAXIMUM_LIST_SIZE),
403 {0, "", 0, NULL, NULL}
404 };
406 //static NDIS_OID supported_oids[ARRAY_SIZE(xennet_oids)];
408 NDIS_STATUS
409 XenNet_OidRequest(NDIS_HANDLE adapter_context, PNDIS_OID_REQUEST oid_request)
410 {
411 NTSTATUS status;
412 int i;
413 NDIS_OID oid;
414 MINIPORT_OID_REQUEST *routine;
416 //FUNCTION_ENTER();
417 switch(oid_request->RequestType)
418 {
419 case NdisRequestQueryInformation:
420 //FUNCTION_MSG("RequestType = NdisRequestQueryInformation\n");
421 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
422 break;
423 case NdisRequestSetInformation:
424 //FUNCTION_MSG("RequestType = NdisRequestSetInformation\n");
425 oid = oid_request->DATA.SET_INFORMATION.Oid;
426 break;
427 case NdisRequestQueryStatistics:
428 //FUNCTION_MSG("RequestType = NdisRequestQueryStatistics\n");
429 oid = oid_request->DATA.QUERY_INFORMATION.Oid;
430 break;
431 default:
432 //FUNCTION_MSG("RequestType = NdisRequestQuery%d\n", oid_request->RequestType);
433 return NDIS_STATUS_NOT_SUPPORTED;
434 }
435 for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);
437 if (!xennet_oids[i].oid)
438 {
439 FUNCTION_MSG("Unsupported OID %08x\n", oid);
440 return NDIS_STATUS_NOT_SUPPORTED;
441 }
442 //FUNCTION_MSG("Oid = %s\n", xennet_oids[i].oid_name);
443 routine = NULL;
444 switch(oid_request->RequestType)
445 {
446 case NdisRequestQueryInformation:
447 case NdisRequestQueryStatistics:
448 if (oid_request->DATA.QUERY_INFORMATION.InformationBufferLength < xennet_oids[i].min_length)
449 {
450 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.QUERY_INFORMATION.InformationBufferLength < xennet_oids[i].min_length);
451 oid_request->DATA.QUERY_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
452 return NDIS_STATUS_BUFFER_TOO_SHORT;
453 }
454 routine = xennet_oids[i].query_routine;
455 break;
456 case NdisRequestSetInformation:
457 if (oid_request->DATA.SET_INFORMATION.InformationBufferLength < xennet_oids[i].min_length)
458 {
459 FUNCTION_MSG("InformationBufferLength %d < min_length %d\n", oid_request->DATA.SET_INFORMATION.InformationBufferLength < xennet_oids[i].min_length);
460 oid_request->DATA.SET_INFORMATION.BytesNeeded = xennet_oids[i].min_length;
461 return NDIS_STATUS_BUFFER_TOO_SHORT;
462 }
463 routine = xennet_oids[i].set_routine;
464 break;
465 }
466 if (!routine)
467 {
468 //FUNCTION_MSG("Operation not supported\n");
469 return NDIS_STATUS_NOT_SUPPORTED;
470 }
471 status = routine(adapter_context, oid_request);
472 //FUNCTION_MSG("status = %08x\n", status);
474 //FUNCTION_EXIT();
475 return status;
476 }
478 VOID
479 XenNet_CancelOidRequest(NDIS_HANDLE adapter_context, PVOID request_id)
480 {
481 UNREFERENCED_PARAMETER(adapter_context);
482 UNREFERENCED_PARAMETER(request_id);
483 FUNCTION_ENTER();
484 FUNCTION_EXIT();
485 }