win-pvdrivers

view xennet/xennet_oid.c @ 783:644e5ddb1b47

Handle SCSI INQUIRY command better in xenvbd
author James Harper <james.harper@bendigoit.com.au>
date Mon Feb 15 20:53:57 2010 +1100 (2010-02-15)
parents 31c56358c9fc
children bf1b18b4728b
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 = MAX_LOOKAHEAD_LENGTH; //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->current_lookahead;
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;
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_EXIT_STATUS(status);
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 (xi = %p)\n", xi));
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 xi->current_lookahead = *(ULONG *)data;
522 KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi));
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 /* 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... */
603 }
604 }
605 memcpy(xi->multicast_list, InformationBuffer, InformationBufferLength);
606 xi->multicast_list_size = InformationBufferLength / 6;
607 status = NDIS_STATUS_SUCCESS;
608 break;
609 case OID_802_3_MAXIMUM_LIST_SIZE:
610 status = NDIS_STATUS_NOT_SUPPORTED;
611 KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
612 break;
613 case OID_TCP_TASK_OFFLOAD:
614 status = NDIS_STATUS_SUCCESS;
615 KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
616 // we should disable everything here, then enable what has been set
617 ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
618 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION)
619 {
620 KdPrint(("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION));
621 status = NDIS_STATUS_INVALID_DATA;
622 break;
623 }
624 if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER))
625 {
626 KdPrint(("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER)));
627 status = NDIS_STATUS_INVALID_DATA;
628 break;
629 }
630 *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
631 offset = ntoh->OffsetFirstTask;
632 nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
633 while (offset != 0)
634 {
635 *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
636 nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
637 switch (nto->Task)
638 {
639 case TcpIpChecksumNdisTask:
640 *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
641 nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
642 KdPrint(("TcpIpChecksumNdisTask\n"));
643 KdPrint((" V4Transmit.IpOptionsSupported = %d\n", nttic->V4Transmit.IpOptionsSupported));
644 KdPrint((" V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported));
645 KdPrint((" V4Transmit.TcpChecksum = %d\n", nttic->V4Transmit.TcpChecksum));
646 KdPrint((" V4Transmit.UdpChecksum = %d\n", nttic->V4Transmit.UdpChecksum));
647 KdPrint((" V4Transmit.IpChecksum = %d\n", nttic->V4Transmit.IpChecksum));
648 KdPrint((" V4Receive.IpOptionsSupported = %d\n", nttic->V4Receive.IpOptionsSupported));
649 KdPrint((" V4Receive.TcpOptionsSupported = %d\n", nttic->V4Receive.TcpOptionsSupported));
650 KdPrint((" V4Receive.TcpChecksum = %d\n", nttic->V4Receive.TcpChecksum));
651 KdPrint((" V4Receive.UdpChecksum = %d\n", nttic->V4Receive.UdpChecksum));
652 KdPrint((" V4Receive.IpChecksum = %d\n", nttic->V4Receive.IpChecksum));
653 KdPrint((" V6Transmit.IpOptionsSupported = %d\n", nttic->V6Transmit.IpOptionsSupported));
654 KdPrint((" V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported));
655 KdPrint((" V6Transmit.TcpChecksum = %d\n", nttic->V6Transmit.TcpChecksum));
656 KdPrint((" V6Transmit.UdpChecksum = %d\n", nttic->V6Transmit.UdpChecksum));
657 KdPrint((" V6Receive.IpOptionsSupported = %d\n", nttic->V6Receive.IpOptionsSupported));
658 KdPrint((" V6Receive.TcpOptionsSupported = %d\n", nttic->V6Receive.TcpOptionsSupported));
659 KdPrint((" V6Receive.TcpChecksum = %d\n", nttic->V6Receive.TcpChecksum));
660 KdPrint((" V6Receive.UdpChecksum = %d\n", nttic->V6Receive.UdpChecksum));
661 /* check for stuff we outright don't support */
662 if (nttic->V6Transmit.IpOptionsSupported ||
663 nttic->V6Transmit.TcpOptionsSupported ||
664 nttic->V6Transmit.TcpChecksum ||
665 nttic->V6Transmit.UdpChecksum ||
666 nttic->V6Receive.IpOptionsSupported ||
667 nttic->V6Receive.TcpOptionsSupported ||
668 nttic->V6Receive.TcpChecksum ||
669 nttic->V6Receive.UdpChecksum)
670 {
671 KdPrint(("IPv6 offload not supported\n"));
672 status = NDIS_STATUS_INVALID_DATA;
673 nttic = NULL;
674 break;
675 }
676 if (nttic->V4Transmit.IpOptionsSupported ||
677 nttic->V4Transmit.IpChecksum)
678 {
679 KdPrint(("IPv4 IP Transmit offload not supported\n"));
680 status = NDIS_STATUS_INVALID_DATA;
681 nttic = NULL;
682 break;
683 }
684 if (nttic->V4Receive.IpOptionsSupported &&
685 !nttic->V4Receive.IpChecksum)
686 {
687 KdPrint(("Invalid combination\n"));
688 status = NDIS_STATUS_INVALID_DATA;
689 nttic = NULL;
690 break;
691 }
692 if (nttic->V4Transmit.TcpOptionsSupported &&
693 !nttic->V4Transmit.TcpChecksum)
694 {
695 KdPrint(("Invalid combination\n"));
696 status = NDIS_STATUS_INVALID_DATA;
697 nttic = NULL;
698 break;
699 }
700 if (nttic->V4Receive.TcpOptionsSupported &&
701 !nttic->V4Receive.TcpChecksum)
702 {
703 KdPrint(("Invalid combination\n"));
704 status = NDIS_STATUS_INVALID_DATA;
705 nttic = NULL;
706 break;
707 }
708 break;
709 case TcpLargeSendNdisTask:
710 *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND);
711 KdPrint(("TcpLargeSendNdisTask\n"));
712 nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
713 KdPrint((" MaxOffLoadSize = %d\n", nttls->MaxOffLoadSize));
714 KdPrint((" MinSegmentCount = %d\n", nttls->MinSegmentCount));
715 KdPrint((" TcpOptions = %d\n", nttls->TcpOptions));
716 KdPrint((" IpOptions = %d\n", nttls->IpOptions));
717 if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS)
718 {
719 KdPrint((" MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS));
720 status = NDIS_STATUS_INVALID_DATA;
721 nttls = NULL;
722 break;
723 }
724 if (nttls->IpOptions)
725 {
726 KdPrint((" IpOptions not supported\n"));
727 status = NDIS_STATUS_INVALID_DATA;
728 nttls = NULL;
729 break;
730 }
731 if (nttls->TcpOptions)
732 {
733 KdPrint((" TcpOptions not supported\n"));
734 status = NDIS_STATUS_INVALID_DATA;
735 nttls = NULL;
736 break;
737 }
738 break;
739 default:
740 KdPrint((" Unknown Task %d\n", nto->Task));
741 }
742 offset = nto->OffsetNextTask;
743 }
744 if (nttic != NULL)
745 xi->setting_csum = *nttic;
746 else
747 {
748 RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
749 KdPrint((" csum offload disabled\n", nto->Task));
750 }
751 if (nttls != NULL)
752 xi->setting_max_offload = nttls->MaxOffLoadSize;
753 else
754 {
755 xi->setting_max_offload = 0;
756 KdPrint((" LSO disabled\n", nto->Task));
757 }
758 break;
759 case OID_PNP_SET_POWER:
760 KdPrint((" Set OID_PNP_SET_POWER\n"));
761 switch (*(PNDIS_DEVICE_POWER_STATE )InformationBuffer)
762 {
763 case NdisDeviceStateD0:
764 KdPrint((" NdisDeviceStateD0\n"));
765 break;
766 case NdisDeviceStateD1:
767 KdPrint((" NdisDeviceStateD1\n"));
768 break;
769 case NdisDeviceStateD2:
770 KdPrint((" NdisDeviceStateD2\n"));
771 break;
772 case NdisDeviceStateD3:
773 KdPrint((" NdisDeviceStateD3\n"));
774 break;
775 default:
776 KdPrint((" NdisDeviceState??\n"));
777 break;
778 }
779 status = NDIS_STATUS_SUCCESS;
780 break;
781 default:
782 KdPrint(("Set Unknown OID 0x%x\n", Oid));
783 status = NDIS_STATUS_NOT_SUPPORTED;
784 break;
785 }
786 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
787 return status;
788 }