win-pvdrivers

view xennet/xennet_oid.c @ 685:c13ccf5a629b

Fixed a bug in the dma routines which was causing memory corruption. In some cases when Windows gave an MDL that was longer than the buffer to be dma'd, the end of the buffer would be overwritten. The only time I am aware of this occuring is on one particular map in Call Of Duty 4.

Split out the dma routines from xenpci_pdo.c into xenpci_dma.c
author James Harper <james.harper@bendigoit.com.au>
date Wed Oct 14 14:46:39 2009 +1100 (2009-10-14)
parents d1754b0e1ead
children 93b98effc8e7
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 // Q = Query Mandatory, S = Set Mandatory
24 NDIS_OID supported_oids[] =
25 {
26 /* general OIDs */
27 OID_GEN_SUPPORTED_LIST, // Q
28 OID_GEN_HARDWARE_STATUS, // Q
29 OID_GEN_MEDIA_SUPPORTED, // Q
30 OID_GEN_MEDIA_IN_USE, // Q
31 OID_GEN_MAXIMUM_LOOKAHEAD, // Q
32 OID_GEN_MAXIMUM_FRAME_SIZE, // Q
33 OID_GEN_LINK_SPEED, // Q
34 OID_GEN_TRANSMIT_BUFFER_SPACE, // Q
35 OID_GEN_RECEIVE_BUFFER_SPACE, // Q
36 OID_GEN_TRANSMIT_BLOCK_SIZE, // Q
37 OID_GEN_RECEIVE_BLOCK_SIZE, // Q
38 OID_GEN_VENDOR_ID, // Q
39 OID_GEN_VENDOR_DESCRIPTION, // Q
40 OID_GEN_CURRENT_PACKET_FILTER, // QS
41 OID_GEN_CURRENT_LOOKAHEAD, // QS
42 OID_GEN_DRIVER_VERSION, // Q
43 OID_GEN_VENDOR_DRIVER_VERSION, // Q
44 OID_GEN_MAXIMUM_TOTAL_SIZE, // Q
45 OID_GEN_PROTOCOL_OPTIONS, // S
46 OID_GEN_MAC_OPTIONS, // Q
47 OID_GEN_MEDIA_CONNECT_STATUS, // Q
48 OID_GEN_MAXIMUM_SEND_PACKETS, // Q
49 /* stats */
50 OID_GEN_XMIT_OK, // Q
51 OID_GEN_RCV_OK, // Q
52 OID_GEN_XMIT_ERROR, // Q
53 OID_GEN_RCV_ERROR, // Q
54 OID_GEN_RCV_NO_BUFFER, // Q
55 /* media-specific OIDs */
56 OID_802_3_PERMANENT_ADDRESS,
57 OID_802_3_CURRENT_ADDRESS,
58 OID_802_3_MULTICAST_LIST,
59 OID_802_3_MAXIMUM_LIST_SIZE,
60 OID_802_3_RCV_ERROR_ALIGNMENT,
61 OID_802_3_XMIT_ONE_COLLISION,
62 OID_802_3_XMIT_MORE_COLLISIONS,
63 /* tcp offload */
64 OID_TCP_TASK_OFFLOAD,
65 /* power */
66 OID_PNP_CAPABILITIES,
67 OID_PNP_SET_POWER,
68 OID_PNP_QUERY_POWER,
69 };
71 /* return 4 or 8 depending on size of buffer */
72 #define HANDLE_STAT_RETURN \
73 {if (InformationBufferLength == 4) { \
74 len = 4; *BytesNeeded = 8; \
75 } else { \
76 len = 8; \
77 } }
79 NDIS_STATUS DDKAPI
80 XenNet_QueryInformation(
81 IN NDIS_HANDLE MiniportAdapterContext,
82 IN NDIS_OID Oid,
83 IN PVOID InformationBuffer,
84 IN ULONG InformationBufferLength,
85 OUT PULONG BytesWritten,
86 OUT PULONG BytesNeeded)
87 {
88 struct xennet_info *xi = MiniportAdapterContext;
89 UCHAR vendor_desc[] = XN_VENDOR_DESC;
90 ULONG64 temp_data;
91 PVOID data = &temp_data;
92 UINT len = 4;
93 BOOLEAN used_temp_buffer = TRUE;
94 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
95 PNDIS_TASK_OFFLOAD_HEADER ntoh;
96 PNDIS_TASK_OFFLOAD nto;
97 PNDIS_TASK_TCP_IP_CHECKSUM nttic;
98 PNDIS_TASK_TCP_LARGE_SEND nttls;
99 PNDIS_PNP_CAPABILITIES npc;
101 *BytesNeeded = 0;
102 *BytesWritten = 0;
104 // FUNCTION_ENTER()
106 switch(Oid)
107 {
108 case OID_GEN_SUPPORTED_LIST:
109 data = supported_oids;
110 len = sizeof(supported_oids);
111 break;
112 case OID_GEN_HARDWARE_STATUS:
113 if (!xi->connected)
114 {
115 temp_data = NdisHardwareStatusInitializing;
116 FUNCTION_MSG("NdisHardwareStatusInitializing\n");
117 }
118 else
119 {
120 temp_data = NdisHardwareStatusReady;
121 FUNCTION_MSG("NdisHardwareStatusReady\n");
122 }
123 break;
124 case OID_GEN_MEDIA_SUPPORTED:
125 temp_data = NdisMedium802_3;
126 break;
127 case OID_GEN_MEDIA_IN_USE:
128 temp_data = NdisMedium802_3;
129 break;
130 case OID_GEN_MAXIMUM_LOOKAHEAD:
131 temp_data = xi->config_mtu;
132 break;
133 case OID_GEN_MAXIMUM_FRAME_SIZE:
134 temp_data = xi->config_mtu;
135 break;
136 case OID_GEN_LINK_SPEED:
137 temp_data = 10000000; /* 1Gb */
138 break;
139 case OID_GEN_TRANSMIT_BUFFER_SPACE:
140 /* multiply this by some small number as we can queue additional packets */
141 temp_data = PAGE_SIZE * NET_TX_RING_SIZE * 4;
142 break;
143 case OID_GEN_RECEIVE_BUFFER_SPACE:
144 temp_data = PAGE_SIZE * NET_RX_RING_SIZE * 2;
145 break;
146 case OID_GEN_TRANSMIT_BLOCK_SIZE:
147 temp_data = PAGE_SIZE; //XN_MAX_PKT_SIZE;
148 break;
149 case OID_GEN_RECEIVE_BLOCK_SIZE:
150 temp_data = PAGE_SIZE; //XN_MAX_PKT_SIZE;
151 break;
152 case OID_GEN_VENDOR_ID:
153 temp_data = 0xFFFFFF; // Not guaranteed to be XENSOURCE_MAC_HDR;
154 break;
155 case OID_GEN_VENDOR_DESCRIPTION:
156 data = vendor_desc;
157 len = sizeof(vendor_desc);
158 break;
159 case OID_GEN_CURRENT_PACKET_FILTER:
160 temp_data = xi->packet_filter;
161 break;
162 case OID_GEN_CURRENT_LOOKAHEAD:
163 temp_data = xi->config_mtu;
164 break;
165 case OID_GEN_DRIVER_VERSION:
166 temp_data = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
167 len = 2;
168 break;
169 case OID_GEN_VENDOR_DRIVER_VERSION:
170 temp_data = VENDOR_DRIVER_VERSION;
171 len = 4;
172 break;
173 case OID_GEN_MAXIMUM_TOTAL_SIZE:
174 temp_data = xi->config_mtu + XN_HDR_SIZE;
175 break;
176 case OID_GEN_MAC_OPTIONS:
177 temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
178 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
179 NDIS_MAC_OPTION_NO_LOOPBACK;
180 break;
181 case OID_GEN_MEDIA_CONNECT_STATUS:
182 if (xi->connected && !xi->inactive)
183 temp_data = NdisMediaStateConnected;
184 else
185 temp_data = NdisMediaStateDisconnected;
186 break;
187 case OID_GEN_MAXIMUM_SEND_PACKETS:
188 /* this is actually ignored for deserialised drivers like us */
189 temp_data = 0; //XN_MAX_SEND_PKTS;
190 break;
191 case OID_GEN_XMIT_OK:
192 temp_data = xi->stat_tx_ok;
193 HANDLE_STAT_RETURN;
194 break;
195 case OID_GEN_RCV_OK:
196 temp_data = xi->stat_rx_ok;
197 HANDLE_STAT_RETURN;
198 break;
199 case OID_GEN_XMIT_ERROR:
200 temp_data = xi->stat_tx_error;
201 HANDLE_STAT_RETURN;
202 break;
203 case OID_GEN_RCV_ERROR:
204 temp_data = xi->stat_rx_error;
205 HANDLE_STAT_RETURN;
206 break;
207 case OID_GEN_RCV_NO_BUFFER:
208 temp_data = xi->stat_rx_no_buffer;
209 HANDLE_STAT_RETURN;
210 break;
211 case OID_802_3_PERMANENT_ADDRESS:
212 data = xi->perm_mac_addr;
213 len = ETH_ALEN;
214 break;
215 case OID_802_3_CURRENT_ADDRESS:
216 data = xi->curr_mac_addr;
217 len = ETH_ALEN;
218 break;
219 case OID_802_3_RCV_ERROR_ALIGNMENT:
220 case OID_802_3_XMIT_ONE_COLLISION:
221 case OID_802_3_XMIT_MORE_COLLISIONS:
222 temp_data = 0;
223 HANDLE_STAT_RETURN;
224 break;
225 case OID_802_3_MULTICAST_LIST:
226 data = xi->multicast_list;
227 len = xi->multicast_list_size * 6;
228 break;
229 case OID_802_3_MAXIMUM_LIST_SIZE:
230 temp_data = MULTICAST_LIST_MAX_SIZE; /* no mcast support, but to return 0 is an error */
231 break;
232 case OID_TCP_TASK_OFFLOAD:
233 KdPrint(("Get OID_TCP_TASK_OFFLOAD\n"));
234 /* it's times like this that C really sucks */
236 len = sizeof(NDIS_TASK_OFFLOAD_HEADER);
238 if (xi->config_csum)
239 {
240 len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
241 + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
242 }
244 if (xi->config_gso)
245 {
246 len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
247 + sizeof(NDIS_TASK_TCP_LARGE_SEND);
248 }
250 //len += 1024;
252 if (len > InformationBufferLength)
253 {
254 break;
255 }
257 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
258 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
259 || ntoh->Size != sizeof(*ntoh)
260 || !(
261 ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation
262 || (ntoh->EncapsulationFormat.Encapsulation == UNSPECIFIED_Encapsulation
263 && ntoh->EncapsulationFormat.EncapsulationHeaderSize == XN_HDR_SIZE)))
264 {
265 status = NDIS_STATUS_NOT_SUPPORTED;
266 break;
267 }
268 ntoh->OffsetFirstTask = 0;
269 nto = NULL;
271 if (xi->config_csum)
272 {
273 if (ntoh->OffsetFirstTask == 0)
274 {
275 ntoh->OffsetFirstTask = ntoh->Size;
276 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
277 }
278 else
279 {
280 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
281 + nto->TaskBufferLength;
282 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
283 }
284 /* fill in first nto */
285 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
286 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
287 nto->Task = TcpIpChecksumNdisTask;
288 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
290 KdPrint(("config_csum enabled\n"));
291 KdPrint(("nto = %p\n", nto));
292 KdPrint(("nto->Size = %d\n", nto->Size));
293 KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
295 /* fill in checksum offload struct */
296 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
297 nttic->V4Transmit.IpChecksum = 0;
298 nttic->V4Transmit.IpOptionsSupported = 0;
299 nttic->V4Transmit.TcpChecksum = 1;
300 nttic->V4Transmit.TcpOptionsSupported = 1;
301 nttic->V4Transmit.UdpChecksum = 1;
302 nttic->V4Receive.IpChecksum = 0;
303 nttic->V4Receive.IpOptionsSupported = 0;
304 nttic->V4Receive.TcpChecksum = 1;
305 nttic->V4Receive.TcpOptionsSupported = 1;
306 nttic->V4Receive.UdpChecksum = 1;
307 nttic->V6Transmit.IpOptionsSupported = 0;
308 nttic->V6Transmit.TcpOptionsSupported = 0;
309 nttic->V6Transmit.TcpChecksum = 0;
310 nttic->V6Transmit.UdpChecksum = 0;
311 nttic->V6Receive.IpOptionsSupported = 0;
312 nttic->V6Receive.TcpOptionsSupported = 0;
313 nttic->V6Receive.TcpChecksum = 0;
314 nttic->V6Receive.UdpChecksum = 0;
315 }
316 if (xi->config_gso)
317 {
318 if (ntoh->OffsetFirstTask == 0)
319 {
320 ntoh->OffsetFirstTask = ntoh->Size;
321 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
322 }
323 else
324 {
325 nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
326 + nto->TaskBufferLength;
327 nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
328 }
330 /* fill in second nto */
331 nto->Version = NDIS_TASK_OFFLOAD_VERSION;
332 nto->Size = sizeof(NDIS_TASK_OFFLOAD);
333 nto->Task = TcpLargeSendNdisTask;
334 nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
336 KdPrint(("config_gso enabled\n"));
337 KdPrint(("nto = %p\n", nto));
338 KdPrint(("nto->Size = %d\n", nto->Size));
339 KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
341 /* fill in large send struct */
342 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
343 nttls->Version = 0;
344 nttls->MaxOffLoadSize = xi->config_gso;
345 nttls->MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
346 nttls->TcpOptions = FALSE; /* linux can't handle this */
347 nttls->IpOptions = FALSE; /* linux can't handle this */
348 KdPrint(("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions)));
349 }
351 if (nto)
352 nto->OffsetNextTask = 0; /* last one */
354 used_temp_buffer = FALSE;
355 break;
356 case OID_IP4_OFFLOAD_STATS:
357 case OID_IP6_OFFLOAD_STATS:
358 /* these are called often so just ignore then quietly */
359 status = NDIS_STATUS_NOT_SUPPORTED;
360 break;
362 case OID_PNP_CAPABILITIES:
363 KdPrint(("Get OID_PNP_CAPABILITIES\n"));
364 len = sizeof(NDIS_PNP_CAPABILITIES);
365 if (len > InformationBufferLength)
366 break;
367 npc = (PNDIS_PNP_CAPABILITIES)InformationBuffer;
368 npc->Flags = 0;
369 npc->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
370 npc->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
371 npc->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
372 used_temp_buffer = FALSE;
373 break;
374 case OID_PNP_QUERY_POWER:
375 KdPrint(("Get OID_PNP_CAPABILITIES\n"));
376 used_temp_buffer = FALSE;
377 break;
379 default:
380 KdPrint(("Get Unknown OID 0x%x\n", Oid));
381 status = NDIS_STATUS_NOT_SUPPORTED;
382 }
384 if (!NT_SUCCESS(status))
385 {
386 // FUNCTION_ERROR_EXIT();
387 return status;
388 }
390 if (len > InformationBufferLength)
391 {
392 *BytesNeeded = len;
393 FUNCTION_MSG("(BUFFER_TOO_SHORT %d > %d)\n", len, InformationBufferLength);
394 return NDIS_STATUS_BUFFER_TOO_SHORT;
395 }
397 *BytesWritten = len;
398 if (len && used_temp_buffer)
399 {
400 NdisMoveMemory((PUCHAR)InformationBuffer, data, len);
401 }
403 //KdPrint(("Got OID 0x%x\n", Oid));
404 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
406 return status;
407 }
409 NDIS_STATUS DDKAPI
410 XenNet_SetInformation(
411 IN NDIS_HANDLE MiniportAdapterContext,
412 IN NDIS_OID Oid,
413 IN PVOID InformationBuffer,
414 IN ULONG InformationBufferLength,
415 OUT PULONG BytesRead,
416 OUT PULONG BytesNeeded
417 )
418 {
419 NTSTATUS status;
420 ULONG i;
421 struct xennet_info *xi = MiniportAdapterContext;
422 PULONG64 data = InformationBuffer;
423 PNDIS_TASK_OFFLOAD_HEADER ntoh;
424 PNDIS_TASK_OFFLOAD nto;
425 PNDIS_TASK_TCP_IP_CHECKSUM nttic = NULL;
426 PNDIS_TASK_TCP_LARGE_SEND nttls = NULL;
427 UCHAR *multicast_list;
428 int offset;
430 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
432 UNREFERENCED_PARAMETER(MiniportAdapterContext);
433 UNREFERENCED_PARAMETER(InformationBufferLength);
434 UNREFERENCED_PARAMETER(BytesRead);
435 UNREFERENCED_PARAMETER(BytesNeeded);
437 switch(Oid)
438 {
439 case OID_GEN_SUPPORTED_LIST:
440 status = NDIS_STATUS_NOT_SUPPORTED;
441 KdPrint(("Unsupported set OID_GEN_SUPPORTED_LIST\n"));
442 break;
443 case OID_GEN_HARDWARE_STATUS:
444 status = NDIS_STATUS_NOT_SUPPORTED;
445 KdPrint(("Unsupported set OID_GEN_HARDWARE_STATUS\n"));
446 break;
447 case OID_GEN_MEDIA_SUPPORTED:
448 status = NDIS_STATUS_NOT_SUPPORTED;
449 KdPrint(("Unsupported set OID_GEN_MEDIA_SUPPORTED\n"));
450 break;
451 case OID_GEN_MEDIA_IN_USE:
452 status = NDIS_STATUS_NOT_SUPPORTED;
453 KdPrint(("Unsupported set OID_GEN_MEDIA_IN_USE\n"));
454 break;
455 case OID_GEN_MAXIMUM_LOOKAHEAD:
456 status = NDIS_STATUS_NOT_SUPPORTED;
457 KdPrint(("Unsupported set OID_GEN_MAXIMUM_LOOKAHEAD\n"));
458 break;
459 case OID_GEN_MAXIMUM_FRAME_SIZE:
460 status = NDIS_STATUS_NOT_SUPPORTED;
461 KdPrint(("Unsupported set OID_GEN_MAXIMUM_FRAME_SIZE\n"));
462 break;
463 case OID_GEN_LINK_SPEED:
464 status = NDIS_STATUS_NOT_SUPPORTED;
465 KdPrint(("Unsupported set OID_GEN_LINK_SPEED\n"));
466 break;
467 case OID_GEN_TRANSMIT_BUFFER_SPACE:
468 status = NDIS_STATUS_NOT_SUPPORTED;
469 KdPrint(("Unsupported set OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
470 break;
471 case OID_GEN_RECEIVE_BUFFER_SPACE:
472 status = NDIS_STATUS_NOT_SUPPORTED;
473 KdPrint(("Unsupported set OID_GEN_RECEIVE_BUFFER_SPACE\n"));
474 break;
475 case OID_GEN_TRANSMIT_BLOCK_SIZE:
476 status = NDIS_STATUS_NOT_SUPPORTED;
477 KdPrint(("Unsupported set OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
478 break;
479 case OID_GEN_RECEIVE_BLOCK_SIZE:
480 status = NDIS_STATUS_NOT_SUPPORTED;
481 KdPrint(("Unsupported set OID_GEN_RECEIVE_BLOCK_SIZE\n"));
482 break;
483 case OID_GEN_VENDOR_ID:
484 status = NDIS_STATUS_NOT_SUPPORTED;
485 KdPrint(("Unsupported set OID_GEN_VENDOR_ID\n"));
486 break;
487 case OID_GEN_VENDOR_DESCRIPTION:
488 status = NDIS_STATUS_NOT_SUPPORTED;
489 KdPrint(("Unsupported set OID_GEN_VENDOR_DESCRIPTION\n"));
490 break;
491 case OID_GEN_CURRENT_PACKET_FILTER:
492 KdPrint(("Set OID_GEN_CURRENT_PACKET_FILTER\n"));
493 if (*(ULONG *)data & NDIS_PACKET_TYPE_DIRECTED)
494 KdPrint((" NDIS_PACKET_TYPE_DIRECTED\n"));
495 if (*(ULONG *)data & NDIS_PACKET_TYPE_MULTICAST)
496 KdPrint((" NDIS_PACKET_TYPE_MULTICAST\n"));
497 if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_MULTICAST)
498 KdPrint((" NDIS_PACKET_TYPE_ALL_MULTICAST\n"));
499 if (*(ULONG *)data & NDIS_PACKET_TYPE_BROADCAST)
500 KdPrint((" NDIS_PACKET_TYPE_BROADCAST\n"));
501 if (*(ULONG *)data & NDIS_PACKET_TYPE_PROMISCUOUS)
502 KdPrint((" NDIS_PACKET_TYPE_PROMISCUOUS\n"));
503 if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
504 KdPrint((" NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n"));
505 if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_LOCAL)
506 KdPrint((" NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n"));
507 if (*(ULONG *)data & NDIS_PACKET_TYPE_FUNCTIONAL)
508 KdPrint((" NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n"));
509 if (*(ULONG *)data & NDIS_PACKET_TYPE_GROUP)
510 KdPrint((" NDIS_PACKET_TYPE_GROUP (not supported)\n"));
511 if (*(ULONG *)data & ~SUPPORTED_PACKET_FILTERS)
512 {
513 status = NDIS_STATUS_NOT_SUPPORTED;
514 KdPrint((" returning NDIS_STATUS_NOT_SUPPORTED\n"));
515 break;
516 }
517 xi->packet_filter = *(ULONG *)data;
518 status = NDIS_STATUS_SUCCESS;
519 break;
520 case OID_GEN_CURRENT_LOOKAHEAD:
521 KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d\n", *(int *)data));
522 // TODO: We should do this...
523 status = NDIS_STATUS_SUCCESS;
524 break;
525 case OID_GEN_DRIVER_VERSION:
526 status = NDIS_STATUS_NOT_SUPPORTED;
527 KdPrint(("Unsupported set OID_GEN_DRIVER_VERSION\n"));
528 break;
529 case OID_GEN_MAXIMUM_TOTAL_SIZE:
530 status = NDIS_STATUS_NOT_SUPPORTED;
531 KdPrint(("Unsupported set OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
532 break;
533 case OID_GEN_PROTOCOL_OPTIONS:
534 KdPrint(("Unsupported set OID_GEN_PROTOCOL_OPTIONS\n"));
535 // TODO - actually do this...
536 status = NDIS_STATUS_SUCCESS;
537 break;
538 case OID_GEN_MAC_OPTIONS:
539 status = NDIS_STATUS_NOT_SUPPORTED;
540 KdPrint(("Unsupported set OID_GEN_MAC_OPTIONS\n"));
541 break;
542 case OID_GEN_MEDIA_CONNECT_STATUS:
543 status = NDIS_STATUS_NOT_SUPPORTED;
544 KdPrint(("Unsupported set OID_GEN_MEDIA_CONNECT_STATUS\n"));
545 break;
546 case OID_GEN_MAXIMUM_SEND_PACKETS:
547 status = NDIS_STATUS_NOT_SUPPORTED;
548 KdPrint(("Unsupported set OID_GEN_MAXIMUM_SEND_PACKETS\n"));
549 break;
550 case OID_GEN_XMIT_OK:
551 status = NDIS_STATUS_NOT_SUPPORTED;
552 KdPrint(("Unsupported set OID_GEN_XMIT_OK\n"));
553 break;
554 case OID_GEN_RCV_OK:
555 status = NDIS_STATUS_NOT_SUPPORTED;
556 KdPrint(("Unsupported set OID_GEN_RCV_OK\n"));
557 break;
558 case OID_GEN_XMIT_ERROR:
559 status = NDIS_STATUS_NOT_SUPPORTED;
560 KdPrint(("Unsupported set OID_GEN_XMIT_ERROR\n"));
561 break;
562 case OID_GEN_RCV_ERROR:
563 status = NDIS_STATUS_NOT_SUPPORTED;
564 KdPrint(("Unsupported set OID_GEN_RCV_ERROR\n"));
565 break;
566 case OID_GEN_RCV_NO_BUFFER:
567 status = NDIS_STATUS_NOT_SUPPORTED;
568 KdPrint(("Unsupported set OID_GEN_RCV_NO_BUFFER\n"));
569 break;
570 case OID_802_3_PERMANENT_ADDRESS:
571 status = NDIS_STATUS_NOT_SUPPORTED;
572 KdPrint(("Unsupported set OID_802_3_PERMANENT_ADDRESS\n"));
573 break;
574 case OID_802_3_CURRENT_ADDRESS:
575 status = NDIS_STATUS_NOT_SUPPORTED;
576 KdPrint(("Unsupported set OID_802_3_CURRENT_ADDRESS\n"));
577 break;
578 case OID_802_3_MULTICAST_LIST:
579 KdPrint((" Set OID_802_3_MULTICAST_LIST\n"));
580 KdPrint((" Length = %d\n", InformationBufferLength));
581 KdPrint((" Entries = %d\n", InformationBufferLength / 6));
582 if (InformationBufferLength > MULTICAST_LIST_MAX_SIZE * 6)
583 {
584 status = NDIS_STATUS_MULTICAST_FULL;
585 break;
586 }
588 if (InformationBufferLength % 6 != 0)
589 {
590 status = NDIS_STATUS_MULTICAST_FULL;
591 break;
592 }
593 multicast_list = InformationBuffer;
594 for (i = 0; i < InformationBufferLength / 6; i++)
595 {
596 if (!(multicast_list[i * 6 + 0] & 0x01))
597 {
598 KdPrint((" Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i,
599 (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1],
600 (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3],
601 (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]));
602 status = NDIS_STATUS_MULTICAST_FULL;
603 break;
604 }
605 }
606 memcpy(xi->multicast_list, InformationBuffer, InformationBufferLength);
607 xi->multicast_list_size = InformationBufferLength / 6;
608 status = NDIS_STATUS_SUCCESS;
609 break;
610 case OID_802_3_MAXIMUM_LIST_SIZE:
611 status = NDIS_STATUS_NOT_SUPPORTED;
612 KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
613 break;
614 case OID_TCP_TASK_OFFLOAD:
615 status = NDIS_STATUS_SUCCESS;
616 KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
617 // we should disable everything here, then enable what has been set
618 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
619 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION)
620 {
621 KdPrint(("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION));
622 status = NDIS_STATUS_INVALID_DATA;
623 break;
624 }
625 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER))
626 {
627 KdPrint(("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER)));
628 status = NDIS_STATUS_INVALID_DATA;
629 break;
630 }
631 *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
632 offset = ntoh->OffsetFirstTask;
633 nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
634 while (offset != 0)
635 {
636 *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
637 nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
638 switch (nto->Task)
639 {
640 case TcpIpChecksumNdisTask:
641 *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
642 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
643 KdPrint(("TcpIpChecksumNdisTask\n"));
644 KdPrint((" V4Transmit.IpOptionsSupported = %d\n", nttic->V4Transmit.IpOptionsSupported));
645 KdPrint((" V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported));
646 KdPrint((" V4Transmit.TcpChecksum = %d\n", nttic->V4Transmit.TcpChecksum));
647 KdPrint((" V4Transmit.UdpChecksum = %d\n", nttic->V4Transmit.UdpChecksum));
648 KdPrint((" V4Transmit.IpChecksum = %d\n", nttic->V4Transmit.IpChecksum));
649 KdPrint((" V4Receive.IpOptionsSupported = %d\n", nttic->V4Receive.IpOptionsSupported));
650 KdPrint((" V4Receive.TcpOptionsSupported = %d\n", nttic->V4Receive.TcpOptionsSupported));
651 KdPrint((" V4Receive.TcpChecksum = %d\n", nttic->V4Receive.TcpChecksum));
652 KdPrint((" V4Receive.UdpChecksum = %d\n", nttic->V4Receive.UdpChecksum));
653 KdPrint((" V4Receive.IpChecksum = %d\n", nttic->V4Receive.IpChecksum));
654 KdPrint((" V6Transmit.IpOptionsSupported = %d\n", nttic->V6Transmit.IpOptionsSupported));
655 KdPrint((" V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported));
656 KdPrint((" V6Transmit.TcpChecksum = %d\n", nttic->V6Transmit.TcpChecksum));
657 KdPrint((" V6Transmit.UdpChecksum = %d\n", nttic->V6Transmit.UdpChecksum));
658 KdPrint((" V6Receive.IpOptionsSupported = %d\n", nttic->V6Receive.IpOptionsSupported));
659 KdPrint((" V6Receive.TcpOptionsSupported = %d\n", nttic->V6Receive.TcpOptionsSupported));
660 KdPrint((" V6Receive.TcpChecksum = %d\n", nttic->V6Receive.TcpChecksum));
661 KdPrint((" V6Receive.UdpChecksum = %d\n", nttic->V6Receive.UdpChecksum));
662 /* check for stuff we outright don't support */
663 if (nttic->V6Transmit.IpOptionsSupported ||
664 nttic->V6Transmit.TcpOptionsSupported ||
665 nttic->V6Transmit.TcpChecksum ||
666 nttic->V6Transmit.UdpChecksum ||
667 nttic->V6Receive.IpOptionsSupported ||
668 nttic->V6Receive.TcpOptionsSupported ||
669 nttic->V6Receive.TcpChecksum ||
670 nttic->V6Receive.UdpChecksum)
671 {
672 KdPrint(("IPv6 offload not supported\n"));
673 status = NDIS_STATUS_INVALID_DATA;
674 nttic = NULL;
675 break;
676 }
677 if (nttic->V4Transmit.IpOptionsSupported ||
678 nttic->V4Transmit.IpChecksum)
679 {
680 KdPrint(("IPv4 IP Transmit offload not supported\n"));
681 status = NDIS_STATUS_INVALID_DATA;
682 nttic = NULL;
683 break;
684 }
685 if (nttic->V4Receive.IpOptionsSupported &&
686 !nttic->V4Receive.IpChecksum)
687 {
688 KdPrint(("Invalid combination\n"));
689 status = NDIS_STATUS_INVALID_DATA;
690 nttic = NULL;
691 break;
692 }
693 if (nttic->V4Transmit.TcpOptionsSupported &&
694 !nttic->V4Transmit.TcpChecksum)
695 {
696 KdPrint(("Invalid combination\n"));
697 status = NDIS_STATUS_INVALID_DATA;
698 nttic = NULL;
699 break;
700 }
701 if (nttic->V4Receive.TcpOptionsSupported &&
702 !nttic->V4Receive.TcpChecksum)
703 {
704 KdPrint(("Invalid combination\n"));
705 status = NDIS_STATUS_INVALID_DATA;
706 nttic = NULL;
707 break;
708 }
709 break;
710 case TcpLargeSendNdisTask:
711 *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND);
712 KdPrint(("TcpLargeSendNdisTask\n"));
713 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
714 KdPrint((" MaxOffLoadSize = %d\n", nttls->MaxOffLoadSize));
715 KdPrint((" MinSegmentCount = %d\n", nttls->MinSegmentCount));
716 KdPrint((" TcpOptions = %d\n", nttls->TcpOptions));
717 KdPrint((" IpOptions = %d\n", nttls->IpOptions));
718 if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS)
719 {
720 KdPrint((" MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS));
721 status = NDIS_STATUS_INVALID_DATA;
722 nttls = NULL;
723 break;
724 }
725 if (nttls->IpOptions)
726 {
727 KdPrint((" IpOptions not supported\n"));
728 status = NDIS_STATUS_INVALID_DATA;
729 nttls = NULL;
730 break;
731 }
732 if (nttls->TcpOptions)
733 {
734 KdPrint((" TcpOptions not supported\n"));
735 status = NDIS_STATUS_INVALID_DATA;
736 nttls = NULL;
737 break;
738 }
739 break;
740 default:
741 KdPrint((" Unknown Task %d\n", nto->Task));
742 }
743 offset = nto->OffsetNextTask;
744 }
745 if (nttic != NULL)
746 xi->setting_csum = *nttic;
747 else
748 {
749 RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
750 KdPrint((" csum offload disabled\n", nto->Task));
751 }
752 if (nttls != NULL)
753 xi->setting_max_offload = nttls->MaxOffLoadSize;
754 else
755 {
756 xi->setting_max_offload = 0;
757 KdPrint((" LSO disabled\n", nto->Task));
758 }
759 break;
760 case OID_PNP_SET_POWER:
761 KdPrint((" Set OID_PNP_SET_POWER\n"));
762 switch (*(PNDIS_DEVICE_POWER_STATE )InformationBuffer)
763 {
764 case NdisDeviceStateD0:
765 KdPrint((" NdisDeviceStateD0\n"));
766 break;
767 case NdisDeviceStateD1:
768 KdPrint((" NdisDeviceStateD1\n"));
769 break;
770 case NdisDeviceStateD2:
771 KdPrint((" NdisDeviceStateD2\n"));
772 break;
773 case NdisDeviceStateD3:
774 KdPrint((" NdisDeviceStateD3\n"));
775 break;
776 default:
777 KdPrint((" NdisDeviceState??\n"));
778 break;
779 }
780 status = NDIS_STATUS_SUCCESS;
781 break;
782 default:
783 KdPrint(("Set Unknown OID 0x%x\n", Oid));
784 status = NDIS_STATUS_NOT_SUPPORTED;
785 break;
786 }
787 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
788 return status;
789 }