1 /*
2 * PROJECT: ReactOS nVidia nForce Ethernet Controller Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Miniport information callbacks
5 * COPYRIGHT: Copyright 2021-2022 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include "nvnet.h"
11
12 #define NDEBUG
13 #include "debug.h"
14
15 /* GLOBALS ********************************************************************/
16
17 static const NDIS_OID NvpSupportedOidList[] =
18 {
19 OID_GEN_SUPPORTED_LIST,
20 OID_GEN_CURRENT_PACKET_FILTER,
21 OID_GEN_HARDWARE_STATUS,
22 OID_GEN_MEDIA_SUPPORTED,
23 OID_GEN_MEDIA_IN_USE,
24 OID_GEN_MAXIMUM_LOOKAHEAD,
25 OID_GEN_MAXIMUM_FRAME_SIZE,
26 OID_GEN_MAXIMUM_SEND_PACKETS,
27 OID_GEN_LINK_SPEED,
28 OID_GEN_TRANSMIT_BUFFER_SPACE,
29 OID_GEN_RECEIVE_BUFFER_SPACE,
30 OID_GEN_RECEIVE_BLOCK_SIZE,
31 OID_GEN_TRANSMIT_BLOCK_SIZE,
32 OID_GEN_VENDOR_ID,
33 OID_GEN_VENDOR_DESCRIPTION,
34 OID_GEN_VENDOR_DRIVER_VERSION,
35 OID_GEN_CURRENT_LOOKAHEAD,
36 OID_GEN_DRIVER_VERSION,
37 OID_GEN_MAXIMUM_TOTAL_SIZE,
38 OID_GEN_MAC_OPTIONS,
39 OID_GEN_MEDIA_CONNECT_STATUS,
40 OID_GEN_VLAN_ID,
41 OID_802_3_PERMANENT_ADDRESS,
42 OID_802_3_CURRENT_ADDRESS,
43 OID_802_3_MULTICAST_LIST,
44 OID_802_3_MAXIMUM_LIST_SIZE,
45
46 /* Statistics */
47 OID_GEN_XMIT_OK,
48 OID_GEN_RCV_OK,
49 OID_GEN_XMIT_ERROR,
50 OID_GEN_RCV_ERROR,
51 OID_GEN_RCV_NO_BUFFER,
52 OID_GEN_DIRECTED_FRAMES_RCV,
53 OID_GEN_RCV_CRC_ERROR,
54 OID_GEN_TRANSMIT_QUEUE_LENGTH,
55 OID_802_3_RCV_ERROR_ALIGNMENT,
56 OID_802_3_XMIT_ONE_COLLISION,
57 OID_802_3_XMIT_MORE_COLLISIONS,
58 OID_802_3_XMIT_DEFERRED,
59 OID_802_3_XMIT_MAX_COLLISIONS,
60 OID_802_3_RCV_OVERRUN,
61 OID_802_3_XMIT_UNDERRUN,
62 OID_802_3_XMIT_HEARTBEAT_FAILURE,
63 OID_802_3_XMIT_TIMES_CRS_LOST,
64 OID_802_3_XMIT_LATE_COLLISIONS,
65
66 /* Offload */
67 OID_TCP_TASK_OFFLOAD,
68
69 /* Power management */
70 OID_PNP_CAPABILITIES,
71 OID_PNP_SET_POWER,
72 OID_PNP_QUERY_POWER,
73 OID_PNP_ADD_WAKE_UP_PATTERN,
74 OID_PNP_REMOVE_WAKE_UP_PATTERN,
75 OID_PNP_ENABLE_WAKE_UP
76 };
77
78 /* FUNCTIONS ******************************************************************/
79
80 static
81 ULONG
NvNetGetLinkSpeed(_In_ PNVNET_ADAPTER Adapter)82 NvNetGetLinkSpeed(
83 _In_ PNVNET_ADAPTER Adapter)
84 {
85 ULONG LinkSpeedMbps;
86
87 switch (Adapter->LinkSpeed)
88 {
89 case NVREG_LINKSPEED_10:
90 LinkSpeedMbps = 10;
91 break;
92 case NVREG_LINKSPEED_100:
93 LinkSpeedMbps = 100;
94 break;
95 case NVREG_LINKSPEED_1000:
96 LinkSpeedMbps = 1000;
97 break;
98
99 default:
100 UNREACHABLE;
101 break;
102 }
103
104 return LinkSpeedMbps;
105 }
106
107 static
108 ULONG
PacketFilterToMask(_In_ ULONG PacketFilter)109 PacketFilterToMask(
110 _In_ ULONG PacketFilter)
111 {
112 ULONG FilterMask = NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR | NVREG_PFF_PROMISC;
113
114 if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
115 {
116 FilterMask &= ~NVREG_PFF_MYADDR;
117 }
118
119 if (PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
120 {
121 FilterMask &= ~NVREG_PFF_PROMISC;
122 }
123
124 return FilterMask;
125 }
126
127 static
128 DECLSPEC_NOINLINE /* Called from pageable code */
129 VOID
NvNetApplyPacketFilter(_In_ PNVNET_ADAPTER Adapter)130 NvNetApplyPacketFilter(
131 _In_ PNVNET_ADAPTER Adapter)
132 {
133 UCHAR Address[ETH_LENGTH_OF_ADDRESS];
134 UCHAR Mask[ETH_LENGTH_OF_ADDRESS];
135 ULONG FilterMask;
136 BOOLEAN RestartReceiver;
137
138 if (Adapter->PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
139 {
140 NdisZeroMemory(Address, sizeof(Address));
141 NdisZeroMemory(Mask, sizeof(Mask));
142
143 Address[0] |= NVREG_MCASTADDRA_FORCE;
144 Mask[0] |= NVREG_MCASTADDRA_FORCE;
145 }
146 else if (Adapter->PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
147 {
148 if (Adapter->MulticastListSize > 0)
149 {
150 ULONG i, j;
151
152 NdisFillMemory(Address, sizeof(Address), 0xFF);
153 NdisFillMemory(Mask, sizeof(Mask), 0xFF);
154
155 for (i = 0; i < Adapter->MulticastListSize; ++i)
156 {
157 PUCHAR MacAddress = Adapter->MulticastList[i].MacAddress;
158
159 for (j = 0; j < ETH_LENGTH_OF_ADDRESS; ++j)
160 {
161 Address[j] &= MacAddress[j];
162 Mask[j] &= ~MacAddress[j];
163 }
164 }
165
166 for (j = 0; j < ETH_LENGTH_OF_ADDRESS; ++j)
167 {
168 Mask[j] |= Address[j];
169 }
170 }
171 else
172 {
173 NdisZeroMemory(Address, sizeof(Address));
174 NdisZeroMemory(Mask, sizeof(Mask));
175 }
176 }
177 else
178 {
179 NdisZeroMemory(Address, sizeof(Address));
180 NdisFillMemory(Mask, sizeof(Mask), 0xFF);
181 }
182
183 FilterMask = NV_READ(Adapter, NvRegPacketFilterFlags) & NVREG_PFF_PAUSE_RX;
184 FilterMask |= PacketFilterToMask(Adapter->PacketFilter);
185
186 NdisAcquireSpinLock(&Adapter->Receive.Lock);
187
188 RestartReceiver = !!(NV_READ(Adapter, NvRegReceiverControl) & NVREG_RCVCTL_START);
189 if (RestartReceiver)
190 {
191 NvNetStopReceiver(Adapter);
192 }
193
194 NV_WRITE(Adapter, NvRegMulticastAddrA,
195 Address[3] << 24 | Address[2] << 16 | Address[1] << 8 | Address[0]);
196 NV_WRITE(Adapter, NvRegMulticastAddrB, Address[5] << 8 | Address[4]);
197 NV_WRITE(Adapter, NvRegMulticastMaskA,
198 Mask[3] << 24 | Mask[2] << 16 | Mask[1] << 8 | Mask[0]);
199 NV_WRITE(Adapter, NvRegMulticastMaskB, Mask[5] << 8 | Mask[4]);
200
201 NV_WRITE(Adapter, NvRegPacketFilterFlags, FilterMask);
202
203 if (RestartReceiver)
204 {
205 NvNetStartReceiver(Adapter);
206 }
207
208 NdisReleaseSpinLock(&Adapter->Receive.Lock);
209 }
210
211 static
212 VOID
NvNetReadStatistics(_In_ PNVNET_ADAPTER Adapter)213 NvNetReadStatistics(
214 _In_ PNVNET_ADAPTER Adapter)
215 {
216 Adapter->Statistics.HwTxCnt += NV_READ(Adapter, NvRegTxCnt);
217 Adapter->Statistics.HwTxZeroReXmt += NV_READ(Adapter, NvRegTxZeroReXmt);
218 Adapter->Statistics.HwTxOneReXmt += NV_READ(Adapter, NvRegTxOneReXmt);
219 Adapter->Statistics.HwTxManyReXmt += NV_READ(Adapter, NvRegTxManyReXmt);
220 Adapter->Statistics.HwTxLateCol += NV_READ(Adapter, NvRegTxLateCol);
221 Adapter->Statistics.HwTxUnderflow += NV_READ(Adapter, NvRegTxUnderflow);
222 Adapter->Statistics.HwTxLossCarrier += NV_READ(Adapter, NvRegTxLossCarrier);
223 Adapter->Statistics.HwTxExcessDef += NV_READ(Adapter, NvRegTxExcessDef);
224 Adapter->Statistics.HwTxRetryErr += NV_READ(Adapter, NvRegTxRetryErr);
225 Adapter->Statistics.HwRxFrameErr += NV_READ(Adapter, NvRegRxFrameErr);
226 Adapter->Statistics.HwRxExtraByte += NV_READ(Adapter, NvRegRxExtraByte);
227 Adapter->Statistics.HwRxLateCol += NV_READ(Adapter, NvRegRxLateCol);
228 Adapter->Statistics.HwRxRunt += NV_READ(Adapter, NvRegRxRunt);
229 Adapter->Statistics.HwRxFrameTooLong += NV_READ(Adapter, NvRegRxFrameTooLong);
230 Adapter->Statistics.HwRxOverflow += NV_READ(Adapter, NvRegRxOverflow);
231 Adapter->Statistics.HwRxFCSErr += NV_READ(Adapter, NvRegRxFCSErr);
232 Adapter->Statistics.HwRxFrameAlignErr += NV_READ(Adapter, NvRegRxFrameAlignErr);
233 Adapter->Statistics.HwRxLenErr += NV_READ(Adapter, NvRegRxLenErr);
234 Adapter->Statistics.HwRxUnicast += NV_READ(Adapter, NvRegRxUnicast);
235 Adapter->Statistics.HwRxMulticast += NV_READ(Adapter, NvRegRxMulticast);
236 Adapter->Statistics.HwRxBroadcast += NV_READ(Adapter, NvRegRxBroadcast);
237
238 if (Adapter->Features & DEV_HAS_STATISTICS_V2)
239 {
240 Adapter->Statistics.HwTxDef += NV_READ(Adapter, NvRegTxDef);
241 Adapter->Statistics.HwTxFrame += NV_READ(Adapter, NvRegTxFrame);
242 Adapter->Statistics.HwRxCnt += NV_READ(Adapter, NvRegRxCnt);
243 Adapter->Statistics.HwTxPause += NV_READ(Adapter, NvRegTxPause);
244 Adapter->Statistics.HwRxPause += NV_READ(Adapter, NvRegRxPause);
245 Adapter->Statistics.HwRxDropFrame += NV_READ(Adapter, NvRegRxDropFrame);
246 }
247
248 if (Adapter->Features & DEV_HAS_STATISTICS_V3)
249 {
250 Adapter->Statistics.HwTxUnicast += NV_READ(Adapter, NvRegTxUnicast);
251 Adapter->Statistics.HwTxMulticast += NV_READ(Adapter, NvRegTxMulticast);
252 Adapter->Statistics.HwTxBroadcast += NV_READ(Adapter, NvRegTxBroadcast);
253 }
254 }
255
256 static
257 VOID
NvNetQueryHwCounter(_In_ PNVNET_ADAPTER Adapter,_In_ NDIS_OID Oid,_Out_ PULONG64 Counter)258 NvNetQueryHwCounter(
259 _In_ PNVNET_ADAPTER Adapter,
260 _In_ NDIS_OID Oid,
261 _Out_ PULONG64 Counter)
262 {
263 switch (Oid)
264 {
265 case OID_GEN_XMIT_OK:
266 *Counter = (Adapter->Features & DEV_HAS_STATISTICS_V2)
267 ? Adapter->Statistics.HwTxFrame
268 : (Adapter->Statistics.HwTxZeroReXmt +
269 Adapter->Statistics.HwTxOneReXmt +
270 Adapter->Statistics.HwTxManyReXmt);
271 break;
272 case OID_GEN_RCV_OK:
273 *Counter = (Adapter->Statistics.HwRxUnicast +
274 Adapter->Statistics.HwRxMulticast +
275 Adapter->Statistics.HwRxBroadcast);
276 break;
277 case OID_GEN_XMIT_ERROR:
278 *Counter = (Adapter->Statistics.HwTxRetryErr +
279 Adapter->Statistics.HwTxLateCol +
280 Adapter->Statistics.HwTxUnderflow +
281 Adapter->Statistics.HwTxLossCarrier +
282 Adapter->Statistics.HwTxExcessDef);
283 break;
284 case OID_GEN_RCV_ERROR:
285 *Counter = (Adapter->Statistics.HwRxFrameAlignErr +
286 Adapter->Statistics.HwRxLenErr +
287 Adapter->Statistics.HwRxRunt +
288 Adapter->Statistics.HwRxFrameTooLong +
289 Adapter->Statistics.HwRxFCSErr +
290 Adapter->Statistics.HwRxFrameErr +
291 Adapter->Statistics.HwRxExtraByte +
292 Adapter->Statistics.HwRxLateCol);
293 break;
294 case OID_GEN_RCV_NO_BUFFER:
295 *Counter = (Adapter->Statistics.HwRxDropFrame +
296 Adapter->Statistics.HwRxOverflow +
297 Adapter->Statistics.ReceiveIrqNoBuffers);
298 break;
299 case OID_GEN_DIRECTED_FRAMES_RCV:
300 *Counter = Adapter->Statistics.HwRxUnicast;
301 break;
302 case OID_GEN_RCV_CRC_ERROR:
303 *Counter = Adapter->Statistics.HwRxFCSErr;
304 break;
305 case OID_802_3_RCV_ERROR_ALIGNMENT:
306 *Counter = Adapter->Statistics.HwRxFrameErr;
307 break;
308 case OID_802_3_XMIT_ONE_COLLISION:
309 *Counter = Adapter->Statistics.HwTxOneReXmt;
310 break;
311 case OID_802_3_XMIT_MORE_COLLISIONS:
312 *Counter = Adapter->Statistics.HwTxManyReXmt;
313 break;
314 case OID_802_3_XMIT_DEFERRED:
315 *Counter = Adapter->Statistics.HwTxDef;
316 break;
317 case OID_802_3_XMIT_MAX_COLLISIONS:
318 *Counter = Adapter->Statistics.HwTxRetryErr;
319 break;
320 case OID_802_3_RCV_OVERRUN:
321 *Counter = Adapter->Statistics.HwRxOverflow;
322 break;
323 case OID_802_3_XMIT_UNDERRUN:
324 *Counter = Adapter->Statistics.HwTxUnderflow;
325 break;
326 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
327 *Counter = Adapter->Statistics.HwTxZeroReXmt;
328 break;
329 case OID_802_3_XMIT_TIMES_CRS_LOST:
330 *Counter = Adapter->Statistics.HwTxLossCarrier;
331 break;
332 case OID_802_3_XMIT_LATE_COLLISIONS:
333 *Counter = Adapter->Statistics.HwTxLateCol;
334 break;
335
336 default:
337 UNREACHABLE;
338 break;
339 }
340 }
341
342 static
343 VOID
NvNetQuerySoftwareCounter(_In_ PNVNET_ADAPTER Adapter,_In_ NDIS_OID Oid,_Out_ PULONG64 Counter)344 NvNetQuerySoftwareCounter(
345 _In_ PNVNET_ADAPTER Adapter,
346 _In_ NDIS_OID Oid,
347 _Out_ PULONG64 Counter)
348 {
349 switch (Oid)
350 {
351 case OID_GEN_XMIT_OK:
352 *Counter = Adapter->Statistics.TransmitOk;
353 break;
354 case OID_GEN_RCV_OK:
355 *Counter = Adapter->Statistics.ReceiveOk;
356 break;
357 case OID_GEN_XMIT_ERROR:
358 *Counter = Adapter->Statistics.TransmitErrors;
359 break;
360 case OID_GEN_RCV_ERROR:
361 *Counter = Adapter->Statistics.ReceiveErrors;
362 break;
363 case OID_GEN_RCV_NO_BUFFER:
364 *Counter = Adapter->Statistics.ReceiveNoBuffers;
365 break;
366 case OID_GEN_DIRECTED_FRAMES_RCV:
367 *Counter = 0;
368 break;
369 case OID_GEN_RCV_CRC_ERROR:
370 *Counter = Adapter->Statistics.ReceiveCrcErrors;
371 break;
372 case OID_802_3_RCV_ERROR_ALIGNMENT:
373 *Counter = Adapter->Statistics.ReceiveAlignmentErrors;
374 break;
375 case OID_802_3_XMIT_ONE_COLLISION:
376 *Counter = Adapter->Statistics.TransmitOneRetry;
377 break;
378 case OID_802_3_XMIT_MORE_COLLISIONS:
379 *Counter = (Adapter->Statistics.TransmitOk -
380 Adapter->Statistics.TransmitOneRetry -
381 Adapter->Statistics.TransmitZeroRetry);
382 break;
383 case OID_802_3_XMIT_DEFERRED:
384 *Counter = Adapter->Statistics.TransmitDeferred;
385 break;
386 case OID_802_3_XMIT_MAX_COLLISIONS:
387 *Counter = Adapter->Statistics.TransmitExcessiveCollisions;
388 break;
389 case OID_802_3_RCV_OVERRUN:
390 *Counter = Adapter->Statistics.ReceiveOverrunErrors;
391 break;
392 case OID_802_3_XMIT_UNDERRUN:
393 *Counter = Adapter->Statistics.TransmitUnderrunErrors;
394 break;
395 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
396 *Counter = Adapter->Statistics.TransmitZeroRetry;
397 break;
398 case OID_802_3_XMIT_TIMES_CRS_LOST:
399 *Counter = Adapter->Statistics.TransmitLostCarrierSense;
400 break;
401 case OID_802_3_XMIT_LATE_COLLISIONS:
402 *Counter = Adapter->Statistics.TransmitLateCollisions;
403 break;
404
405 default:
406 UNREACHABLE;
407 break;
408 }
409 }
410
411 static
412 NDIS_STATUS
NvNetFillPowerManagementCapabilities(_In_ PNVNET_ADAPTER Adapter,_Out_ PNDIS_PNP_CAPABILITIES Capabilities)413 NvNetFillPowerManagementCapabilities(
414 _In_ PNVNET_ADAPTER Adapter,
415 _Out_ PNDIS_PNP_CAPABILITIES Capabilities)
416 {
417 Capabilities->WakeUpCapabilities.MinMagicPacketWakeUp =
418 Capabilities->WakeUpCapabilities.MinPatternWakeUp =
419 Capabilities->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateD3;
420
421 /* All hardware is PM-aware */
422 return NDIS_STATUS_SUCCESS;
423 }
424
425 static
426 ULONG
BuildFrameSignature(_In_ PNVNET_WAKE_FRAME WakeFrame)427 BuildFrameSignature(
428 _In_ PNVNET_WAKE_FRAME WakeFrame)
429 {
430 ULONG i, j, Crc;
431
432 Crc = 0xFFFFFFFF;
433 for (i = 0; i < sizeof(WakeFrame->WakeUpPattern); ++i)
434 {
435 if (WakeFrame->PatternMask.AsUCHAR[i / 8] & (1 << (i % 8)))
436 {
437 Crc ^= WakeFrame->WakeUpPattern[i];
438 for (j = 8; j > 0; --j)
439 {
440 Crc = (Crc >> 1) ^ (-(LONG)(Crc & 1) & 0xEDB88320);
441 }
442 }
443 }
444
445 return ~Crc;
446 }
447
448 static
449 VOID
WriteWakeFrame(_In_ PNVNET_ADAPTER Adapter,_In_ PNVNET_WAKE_FRAME WakeFrame,_In_ ULONG FrameNumber)450 WriteWakeFrame(
451 _In_ PNVNET_ADAPTER Adapter,
452 _In_ PNVNET_WAKE_FRAME WakeFrame,
453 _In_ ULONG FrameNumber)
454 {
455 ULONG Offset = FrameNumber * 5 * sizeof(ULONG);
456
457 if (FrameNumber >= NV_WAKEUPPATTERNS)
458 {
459 Offset += NV_PATTERN_V2_OFFSET;
460 }
461
462 NV_WRITE(Adapter, NvRegPatternCrc + Offset, BuildFrameSignature(WakeFrame));
463 NV_WRITE(Adapter, NvRegPatternMask0 + Offset, WakeFrame->PatternMask.AsULONG[0]);
464 NV_WRITE(Adapter, NvRegPatternMask1 + Offset, WakeFrame->PatternMask.AsULONG[1]);
465 NV_WRITE(Adapter, NvRegPatternMask2 + Offset, WakeFrame->PatternMask.AsULONG[2]);
466 NV_WRITE(Adapter, NvRegPatternMask3 + Offset, WakeFrame->PatternMask.AsULONG[3]);
467 }
468
469 static
470 ULONG
FrameNumberToWakeUpMask(_In_ ULONG FrameNumber)471 FrameNumberToWakeUpMask(
472 _In_ ULONG FrameNumber)
473 {
474 if (FrameNumber < 5)
475 return 0x10000 << FrameNumber;
476 else
477 return 0;
478 }
479
480 static
481 ULONG
FrameNumberToPowerMask(_In_ ULONG FrameNumber)482 FrameNumberToPowerMask(
483 _In_ ULONG FrameNumber)
484 {
485 switch (FrameNumber)
486 {
487 case 5:
488 return NVREG_POWERSTATE2_WAKEUPPAT_5;
489 case 6:
490 return NVREG_POWERSTATE2_WAKEUPPAT_6;
491 case 7:
492 return NVREG_POWERSTATE2_WAKEUPPAT_7;
493
494 default:
495 return 0;
496 }
497 }
498
499 VOID
NvNetSetPowerState(_In_ PNVNET_ADAPTER Adapter,_In_ NDIS_DEVICE_POWER_STATE NewPowerState,_In_ ULONG WakeFlags)500 NvNetSetPowerState(
501 _In_ PNVNET_ADAPTER Adapter,
502 _In_ NDIS_DEVICE_POWER_STATE NewPowerState,
503 _In_ ULONG WakeFlags)
504 {
505 ULONG i, PowerState, PowerState2, WakeUpFlags;
506
507 NV_READ(Adapter, NvRegPowerCap);
508
509 WakeUpFlags = 0;
510 PowerState2 = 0;
511 if (Adapter->Features & DEV_HAS_POWER_CNTRL)
512 {
513 PowerState2 = NV_READ(Adapter, NvRegPowerState2);
514 PowerState2 &= ~(NVREG_POWERSTATE2_WAKEUPPAT_5 |
515 NVREG_POWERSTATE2_WAKEUPPAT_6 |
516 NVREG_POWERSTATE2_WAKEUPPAT_7);
517 }
518
519 if (NewPowerState != NdisDeviceStateD0)
520 {
521 ULONG FramesEnabled = 0;
522
523 if (WakeFlags & NDIS_PNP_WAKE_UP_PATTERN_MATCH)
524 WakeUpFlags |= NVREG_WAKEUPFLAGS_ENABLE_MAGPAT;
525 if (WakeFlags & NDIS_PNP_WAKE_UP_LINK_CHANGE)
526 WakeUpFlags |= NVREG_WAKEUPFLAGS_ENABLE_LINKCHANGE;
527 if (WakeFlags & NDIS_PNP_WAKE_UP_MAGIC_PACKET)
528 {
529 WakeUpFlags |= NVREG_WAKEUPFLAGS_ENABLE_WAKEUPPAT;
530
531 for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i)
532 {
533 PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i];
534
535 if (!WakeFrame)
536 continue;
537
538 WriteWakeFrame(Adapter, WakeFrame, i);
539
540 PowerState2 |= FrameNumberToPowerMask(i);
541 WakeUpFlags |= FrameNumberToWakeUpMask(i);
542
543 ++FramesEnabled;
544 }
545 }
546
547 if (WakeUpFlags)
548 {
549 if (!(Adapter->Flags & NV_MAC_IN_USE))
550 {
551 PowerState2 &= ~NVREG_POWERSTATE2_GATE_CLOCKS;
552 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCK_3;
553
554 if (!FramesEnabled && (WakeUpFlags & NVREG_WAKEUPFLAGS_ENABLE_LINKCHANGE))
555 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCK_1;
556 if (FramesEnabled < NV_WAKEUPMASKENTRIES)
557 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCK_2;
558 }
559
560 NvNetStartReceiver(Adapter);
561 }
562 else
563 {
564 if (!(Adapter->Flags & NV_MAC_IN_USE))
565 PowerState2 |= NVREG_POWERSTATE2_GATE_CLOCKS;
566 }
567 }
568
569 NdisStallExecution(NV_POWER_STALL);
570
571 NV_WRITE(Adapter, NvRegWakeUpFlags, WakeUpFlags);
572 if (Adapter->Features & DEV_HAS_POWER_CNTRL)
573 {
574 NV_WRITE(Adapter, NvRegPowerState2, PowerState2);
575 }
576
577 NV_WRITE(Adapter, NvRegPowerState,
578 NV_READ(Adapter, NvRegPowerState) | NVREG_POWERSTATE_POWEREDUP);
579 for (i = 0; i < NV_POWER_ATTEMPTS; ++i)
580 {
581 ULONG State = NV_READ(Adapter, NvRegPowerState);
582
583 if (!(State & NVREG_POWERSTATE_POWEREDUP))
584 break;
585
586 NV_WRITE(Adapter, NvRegPowerState, State | NVREG_POWERSTATE_POWEREDUP);
587
588 NdisStallExecution(NV_POWER_DELAY);
589 }
590
591 PowerState = NewPowerState - 1;
592 if (WakeUpFlags)
593 {
594 PowerState |= NVREG_POWERSTATE_VALID;
595 }
596 NV_WRITE(Adapter, NvRegPowerState, PowerState);
597 }
598
599 static
600 CODE_SEG("PAGE")
601 VOID
602 NTAPI
NvNetPowerWorker(_In_ PNDIS_WORK_ITEM WorkItem,_In_opt_ PVOID Context)603 NvNetPowerWorker(
604 _In_ PNDIS_WORK_ITEM WorkItem,
605 _In_opt_ PVOID Context)
606 {
607 PNVNET_ADAPTER Adapter = Context;
608
609 UNREFERENCED_PARAMETER(WorkItem);
610
611 PAGED_CODE();
612
613 if (Adapter->PowerStatePending == NdisDeviceStateD0)
614 {
615 NvNetSetPowerState(Adapter, NdisDeviceStateD0, 0);
616
617 NT_VERIFY(NvNetInitNIC(Adapter, TRUE) == NDIS_STATUS_SUCCESS);
618
619 NvNetStartAdapter(Adapter);
620
621 NvNetApplyPacketFilter(Adapter);
622 }
623 else
624 {
625 NvNetPauseProcessing(Adapter);
626
627 NvNetStopAdapter(Adapter);
628
629 NvNetIdleTransmitter(Adapter, FALSE);
630 NvNetStopTransmitter(Adapter);
631 NvNetStopReceiver(Adapter);
632 NV_WRITE(Adapter, NvRegTxRxControl,
633 Adapter->TxRxControl | NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET);
634 NdisStallExecution(NV_TXRX_RESET_DELAY);
635
636 NvNetFlushTransmitQueue(Adapter, NDIS_STATUS_FAILURE);
637
638 NvNetSetPowerState(Adapter, Adapter->PowerStatePending, Adapter->WakeFlags);
639 }
640
641 NdisMSetInformationComplete(Adapter->AdapterHandle, NDIS_STATUS_SUCCESS);
642 }
643
644 static
645 NDIS_STATUS
NvNetSetPower(_In_ PNVNET_ADAPTER Adapter,_In_ NDIS_DEVICE_POWER_STATE NewPowerState)646 NvNetSetPower(
647 _In_ PNVNET_ADAPTER Adapter,
648 _In_ NDIS_DEVICE_POWER_STATE NewPowerState)
649 {
650 Adapter->PowerStatePending = NewPowerState;
651
652 NdisInitializeWorkItem(&Adapter->PowerWorkItem, NvNetPowerWorker, Adapter);
653 NdisScheduleWorkItem(&Adapter->PowerWorkItem);
654
655 return NDIS_STATUS_PENDING;
656 }
657
658 static
659 NDIS_STATUS
NvNetAddWakeUpPattern(_In_ PNVNET_ADAPTER Adapter,_In_ PNDIS_PM_PACKET_PATTERN Pattern)660 NvNetAddWakeUpPattern(
661 _In_ PNVNET_ADAPTER Adapter,
662 _In_ PNDIS_PM_PACKET_PATTERN Pattern)
663 {
664 ULONG FrameNumber;
665 NDIS_STATUS Status;
666 PNVNET_WAKE_FRAME WakeFrame;
667
668 if (!_BitScanForward(&FrameNumber, Adapter->WakeFrameBitmap))
669 {
670 return NDIS_STATUS_RESOURCES;
671 }
672
673 Status = NdisAllocateMemoryWithTag((PVOID*)&WakeFrame, sizeof(*WakeFrame), NVNET_TAG);
674 if (Status != NDIS_STATUS_SUCCESS)
675 {
676 return NDIS_STATUS_RESOURCES;
677 }
678
679 Adapter->WakeFrameBitmap &= ~(1 << FrameNumber);
680
681 NdisZeroMemory(WakeFrame, sizeof(*WakeFrame));
682 NdisMoveMemory(&WakeFrame->PatternMask,
683 (PUCHAR)Pattern + sizeof(NDIS_PM_PACKET_PATTERN),
684 min(Pattern->MaskSize, 16));
685 NdisMoveMemory(&WakeFrame->WakeUpPattern,
686 (PUCHAR)Pattern + Pattern->PatternOffset,
687 min(Pattern->PatternSize, 128));
688 Adapter->WakeFrames[FrameNumber] = WakeFrame;
689
690 /* TODO: VLAN frame translation */
691
692 return NDIS_STATUS_SUCCESS;
693 }
694
695 static
696 NDIS_STATUS
NvNetRemoveWakeUpPattern(_In_ PNVNET_ADAPTER Adapter,_In_ PNDIS_PM_PACKET_PATTERN Pattern)697 NvNetRemoveWakeUpPattern(
698 _In_ PNVNET_ADAPTER Adapter,
699 _In_ PNDIS_PM_PACKET_PATTERN Pattern)
700 {
701 ULONG i;
702
703 for (i = 0; i < RTL_NUMBER_OF(Adapter->WakeFrames); ++i)
704 {
705 PNVNET_WAKE_FRAME WakeFrame = Adapter->WakeFrames[i];
706
707 if (!WakeFrame)
708 continue;
709
710 if (!NdisEqualMemory(&WakeFrame->PatternMask,
711 (PUCHAR)Pattern + sizeof(NDIS_PM_PACKET_PATTERN),
712 min(Pattern->MaskSize, 16)))
713 {
714 continue;
715 }
716
717 if (!NdisEqualMemory(&WakeFrame->WakeUpPattern,
718 (PUCHAR)Pattern + Pattern->PatternOffset,
719 min(Pattern->PatternSize, 128)))
720 {
721 continue;
722 }
723
724 NdisFreeMemory(WakeFrame, sizeof(*WakeFrame), 0);
725
726 Adapter->WakeFrameBitmap |= (1 << i);
727 Adapter->WakeFrames[i] = NULL;
728
729 return NDIS_STATUS_SUCCESS;
730 }
731
732 return NDIS_STATUS_INVALID_DATA;
733 }
734
735 static
736 ULONG
NvNetGetWakeUp(_In_ PNVNET_ADAPTER Adapter)737 NvNetGetWakeUp(
738 _In_ PNVNET_ADAPTER Adapter)
739 {
740 return Adapter->WakeFlags & (NDIS_PNP_WAKE_UP_MAGIC_PACKET |
741 NDIS_PNP_WAKE_UP_PATTERN_MATCH |
742 NDIS_PNP_WAKE_UP_LINK_CHANGE);
743 }
744
745 static
746 VOID
NvNetEnableWakeUp(_In_ PNVNET_ADAPTER Adapter,_In_ ULONG Flags)747 NvNetEnableWakeUp(
748 _In_ PNVNET_ADAPTER Adapter,
749 _In_ ULONG Flags)
750 {
751 Adapter->WakeFlags = Flags;
752 }
753
754 static
755 NDIS_STATUS
NvNetGetTcpTaskOffload(_In_ PNVNET_ADAPTER Adapter,_In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader,_In_ ULONG InformationBufferLength,_Out_ PULONG BytesWritten,_Out_ PULONG BytesNeeded)756 NvNetGetTcpTaskOffload(
757 _In_ PNVNET_ADAPTER Adapter,
758 _In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader,
759 _In_ ULONG InformationBufferLength,
760 _Out_ PULONG BytesWritten,
761 _Out_ PULONG BytesNeeded)
762 {
763 ULONG InfoLength;
764 PNDIS_TASK_OFFLOAD TaskOffload;
765
766 if (!(Adapter->Flags & (NV_SEND_CHECKSUM | NV_SEND_LARGE_SEND)))
767 {
768 *BytesWritten = 0;
769 *BytesNeeded = 0;
770 return NDIS_STATUS_NOT_SUPPORTED;
771 }
772
773 InfoLength = sizeof(NDIS_TASK_OFFLOAD_HEADER);
774 if (Adapter->Flags & NV_SEND_CHECKSUM)
775 {
776 InfoLength += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
777 sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
778 }
779 if (Adapter->Flags & NV_SEND_LARGE_SEND)
780 {
781 InfoLength += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
782 sizeof(NDIS_TASK_TCP_LARGE_SEND);
783 }
784
785 if (InformationBufferLength < InfoLength)
786 {
787 *BytesWritten = 0;
788 *BytesNeeded = InfoLength;
789 return NDIS_STATUS_BUFFER_TOO_SHORT;
790 }
791
792 if ((TaskOffloadHeader->EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation) &&
793 (TaskOffloadHeader->EncapsulationFormat.Encapsulation != UNSPECIFIED_Encapsulation ||
794 TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize != sizeof(ETH_HEADER)))
795 {
796 *BytesWritten = 0;
797 *BytesNeeded = 0;
798 return NDIS_STATUS_NOT_SUPPORTED;
799 }
800 if (TaskOffloadHeader->Version != NDIS_TASK_OFFLOAD_VERSION)
801 {
802 *BytesWritten = 0;
803 *BytesNeeded = 0;
804 return NDIS_STATUS_NOT_SUPPORTED;
805 }
806
807 TaskOffloadHeader->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);
808 TaskOffload = (PNDIS_TASK_OFFLOAD)(TaskOffloadHeader + 1);
809 if (Adapter->Flags & NV_SEND_CHECKSUM)
810 {
811 PNDIS_TASK_TCP_IP_CHECKSUM ChecksumTask;
812
813 TaskOffload->Size = sizeof(NDIS_TASK_OFFLOAD);
814 TaskOffload->Version = NDIS_TASK_OFFLOAD_VERSION;
815 TaskOffload->Task = TcpIpChecksumNdisTask;
816 TaskOffload->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
817 TaskOffload->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer) +
818 sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
819
820 ChecksumTask = (PNDIS_TASK_TCP_IP_CHECKSUM)TaskOffload->TaskBuffer;
821 NdisZeroMemory(ChecksumTask, sizeof(*ChecksumTask));
822
823 ChecksumTask->V4Transmit.IpOptionsSupported = 1;
824 ChecksumTask->V4Transmit.TcpOptionsSupported = 1;
825 ChecksumTask->V4Transmit.TcpChecksum = 1;
826 ChecksumTask->V4Transmit.UdpChecksum = 1;
827 ChecksumTask->V4Transmit.IpChecksum = 1;
828
829 ChecksumTask->V4Receive.IpOptionsSupported = 1;
830 ChecksumTask->V4Receive.TcpOptionsSupported = 1;
831 ChecksumTask->V4Receive.TcpChecksum = 1;
832 ChecksumTask->V4Receive.UdpChecksum = 1;
833 ChecksumTask->V4Receive.IpChecksum = 1;
834
835 TaskOffload = (PNDIS_TASK_OFFLOAD)(ChecksumTask + 1);
836 }
837 if (Adapter->Flags & NV_SEND_LARGE_SEND)
838 {
839 PNDIS_TASK_TCP_LARGE_SEND LargeSendTask;
840
841 TaskOffload->Size = sizeof(NDIS_TASK_OFFLOAD);
842 TaskOffload->Version = NDIS_TASK_OFFLOAD_VERSION;
843 TaskOffload->Task = TcpLargeSendNdisTask;
844 TaskOffload->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
845 TaskOffload->OffsetNextTask = 0;
846
847 LargeSendTask = (PNDIS_TASK_TCP_LARGE_SEND)TaskOffload->TaskBuffer;
848 LargeSendTask->Version = NDIS_TASK_TCP_LARGE_SEND_V0;
849 LargeSendTask->MinSegmentCount = NVNET_MINIMUM_LSO_SEGMENT_COUNT;
850 LargeSendTask->MaxOffLoadSize = NVNET_MAXIMUM_LSO_FRAME_SIZE;
851 LargeSendTask->IpOptions = TRUE;
852 LargeSendTask->TcpOptions = TRUE;
853 }
854 TaskOffload->OffsetNextTask = 0;
855
856 *BytesWritten = InfoLength;
857 *BytesNeeded = 0;
858
859 return NDIS_STATUS_SUCCESS;
860 }
861
862 static
863 NDIS_STATUS
NvNetSetTcpTaskOffload(_Inout_ PNVNET_ADAPTER Adapter,_In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader,_In_ PULONG BytesRead)864 NvNetSetTcpTaskOffload(
865 _Inout_ PNVNET_ADAPTER Adapter,
866 _In_ PNDIS_TASK_OFFLOAD_HEADER TaskOffloadHeader,
867 _In_ PULONG BytesRead)
868 {
869 ULONG Offset;
870 PNDIS_TASK_OFFLOAD TaskOffload;
871
872 if (TaskOffloadHeader->Version != NDIS_TASK_OFFLOAD_VERSION)
873 {
874 return NDIS_STATUS_NOT_SUPPORTED;
875 }
876
877 Adapter->IpHeaderOffset = TaskOffloadHeader->EncapsulationFormat.EncapsulationHeaderSize;
878
879 TaskOffload = (PNDIS_TASK_OFFLOAD)TaskOffloadHeader;
880 Offset = TaskOffloadHeader->OffsetFirstTask;
881
882 while (Offset)
883 {
884 *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
885
886 TaskOffload = (PNDIS_TASK_OFFLOAD)((PUCHAR)TaskOffload + Offset);
887 switch (TaskOffload->Task)
888 {
889 case TcpIpChecksumNdisTask:
890 {
891 PNDIS_TASK_TCP_IP_CHECKSUM Task;
892
893 *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
894
895 if (!(Adapter->Flags & NV_SEND_CHECKSUM))
896 {
897 return NDIS_STATUS_NOT_SUPPORTED;
898 }
899
900 Task = (PNDIS_TASK_TCP_IP_CHECKSUM)TaskOffload->TaskBuffer;
901
902 Adapter->Offload.SendTcpChecksum = Task->V4Transmit.TcpChecksum;
903 Adapter->Offload.SendUdpChecksum = Task->V4Transmit.UdpChecksum;
904 Adapter->Offload.SendIpChecksum = Task->V4Transmit.IpChecksum;
905
906 Adapter->Offload.ReceiveTcpChecksum = Task->V4Receive.TcpChecksum;
907 Adapter->Offload.ReceiveUdpChecksum = Task->V4Receive.UdpChecksum;
908 Adapter->Offload.ReceiveIpChecksum = Task->V4Receive.IpChecksum;
909 break;
910 }
911
912 case TcpLargeSendNdisTask:
913 {
914 PNDIS_TASK_TCP_LARGE_SEND Task;
915
916 if (!(Adapter->Flags & NV_SEND_LARGE_SEND))
917 {
918 return NDIS_STATUS_NOT_SUPPORTED;
919 }
920
921 if ((TaskOffloadHeader->
922 EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation) &&
923 (TaskOffloadHeader->
924 EncapsulationFormat.Encapsulation != UNSPECIFIED_Encapsulation ||
925 TaskOffloadHeader->
926 EncapsulationFormat.EncapsulationHeaderSize != sizeof(ETH_HEADER)))
927 {
928 return NDIS_STATUS_NOT_SUPPORTED;
929 }
930
931 *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND);
932
933 Task = (PNDIS_TASK_TCP_LARGE_SEND)TaskOffload->TaskBuffer;
934
935 if (Task->MinSegmentCount != NVNET_MINIMUM_LSO_SEGMENT_COUNT)
936 return NDIS_STATUS_NOT_SUPPORTED;
937
938 if (Task->MaxOffLoadSize > NVNET_MAXIMUM_LSO_FRAME_SIZE)
939 return NDIS_STATUS_NOT_SUPPORTED;
940
941 /* Nothing to do */
942 break;
943 }
944
945 default:
946 break;
947 }
948
949 Offset = TaskOffload->OffsetNextTask;
950 }
951
952 NdisAcquireSpinLock(&Adapter->Send.Lock);
953
954 if (Adapter->Offload.ReceiveTcpChecksum ||
955 Adapter->Offload.ReceiveUdpChecksum ||
956 Adapter->Offload.ReceiveIpChecksum)
957 {
958 Adapter->TxRxControl |= NVREG_TXRXCTL_RXCHECK;
959 }
960 else
961 {
962 Adapter->TxRxControl &= ~NVREG_TXRXCTL_RXCHECK;
963 }
964 NV_WRITE(Adapter, NvRegTxRxControl, Adapter->TxRxControl);
965
966 NdisReleaseSpinLock(&Adapter->Send.Lock);
967
968 return NDIS_STATUS_SUCCESS;
969 }
970
971 NDIS_STATUS
972 NTAPI
MiniportQueryInformation(_In_ NDIS_HANDLE MiniportAdapterContext,_In_ NDIS_OID Oid,_In_ PVOID InformationBuffer,_In_ ULONG InformationBufferLength,_Out_ PULONG BytesWritten,_Out_ PULONG BytesNeeded)973 MiniportQueryInformation(
974 _In_ NDIS_HANDLE MiniportAdapterContext,
975 _In_ NDIS_OID Oid,
976 _In_ PVOID InformationBuffer,
977 _In_ ULONG InformationBufferLength,
978 _Out_ PULONG BytesWritten,
979 _Out_ PULONG BytesNeeded)
980 {
981 PNVNET_ADAPTER Adapter = (PNVNET_ADAPTER)MiniportAdapterContext;
982 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
983 ULONG InfoLength;
984 PVOID InfoPtr;
985 union _GENERIC_INFORMATION
986 {
987 USHORT Ushort;
988 ULONG Ulong;
989 ULONG64 Ulong64;
990 NDIS_MEDIUM Medium;
991 NDIS_HARDWARE_STATUS Status;
992 NDIS_DEVICE_POWER_STATE PowerState;
993 } GenericInfo;
994
995 InfoLength = sizeof(ULONG);
996 InfoPtr = &GenericInfo;
997
998 switch (Oid)
999 {
1000 case OID_GEN_SUPPORTED_LIST:
1001 InfoPtr = (PVOID)&NvpSupportedOidList;
1002 InfoLength = sizeof(NvpSupportedOidList);
1003 break;
1004
1005 case OID_GEN_HARDWARE_STATUS:
1006 InfoLength = sizeof(NDIS_HARDWARE_STATUS);
1007 GenericInfo.Status = NdisHardwareStatusReady;
1008 break;
1009
1010 case OID_GEN_MEDIA_SUPPORTED:
1011 case OID_GEN_MEDIA_IN_USE:
1012 {
1013 InfoLength = sizeof(NDIS_MEDIUM);
1014 GenericInfo.Medium = NdisMedium802_3;
1015 break;
1016 }
1017
1018 case OID_GEN_CURRENT_LOOKAHEAD:
1019 case OID_GEN_MAXIMUM_LOOKAHEAD:
1020 {
1021 GenericInfo.Ulong = Adapter->MaximumFrameSize - sizeof(ETH_HEADER);
1022 break;
1023 }
1024
1025 case OID_GEN_MAXIMUM_FRAME_SIZE:
1026 {
1027 GenericInfo.Ulong = Adapter->MaximumFrameSize;
1028 break;
1029 }
1030
1031 case OID_GEN_LINK_SPEED:
1032 {
1033 GenericInfo.Ulong = NvNetGetLinkSpeed(Adapter) * 10000;
1034 break;
1035 }
1036
1037 case OID_GEN_TRANSMIT_BUFFER_SPACE:
1038 {
1039 /* TODO: Change this later, once the driver can handle multipacket sends */
1040 GenericInfo.Ulong = Adapter->MaximumFrameSize;
1041 break;
1042 }
1043
1044 case OID_GEN_RECEIVE_BUFFER_SPACE:
1045 {
1046 GenericInfo.Ulong = Adapter->MaximumFrameSize * NVNET_RECEIVE_DESCRIPTORS;
1047 }
1048
1049 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1050 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1051 case OID_GEN_RECEIVE_BLOCK_SIZE:
1052 {
1053 GenericInfo.Ulong = Adapter->MaximumFrameSize;
1054 break;
1055 }
1056
1057 case OID_GEN_VENDOR_ID:
1058 {
1059 GenericInfo.Ulong = 0;
1060 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[0] << 16);
1061 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[1] << 8);
1062 GenericInfo.Ulong |= (Adapter->PermanentMacAddress[2] & 0xFF);
1063 break;
1064 }
1065
1066 case OID_GEN_DRIVER_VERSION:
1067 {
1068 InfoLength = sizeof(USHORT);
1069 GenericInfo.Ushort = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
1070 break;
1071 }
1072
1073 case OID_GEN_VENDOR_DESCRIPTION:
1074 {
1075 static const CHAR VendorDesc[] = "nVidia nForce Ethernet Controller";
1076 InfoPtr = (PVOID)&VendorDesc;
1077 InfoLength = sizeof(VendorDesc);
1078 break;
1079 }
1080
1081 case OID_GEN_CURRENT_PACKET_FILTER:
1082 {
1083 GenericInfo.Ulong = Adapter->PacketFilter;
1084 break;
1085 }
1086
1087 case OID_GEN_MAC_OPTIONS:
1088 {
1089 GenericInfo.Ulong = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
1090 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
1091 NDIS_MAC_OPTION_NO_LOOPBACK;
1092
1093 if (Adapter->Flags & NV_PACKET_PRIORITY)
1094 GenericInfo.Ulong |= NDIS_MAC_OPTION_8021P_PRIORITY;
1095 if (Adapter->Flags & NV_VLAN_TAGGING)
1096 GenericInfo.Ulong |= NDIS_MAC_OPTION_8021Q_VLAN;
1097 break;
1098 }
1099
1100 case OID_GEN_MEDIA_CONNECT_STATUS:
1101 {
1102 GenericInfo.Ulong = Adapter->Connected ? NdisMediaStateConnected
1103 : NdisMediaStateDisconnected;
1104 break;
1105 }
1106
1107 case OID_GEN_MAXIMUM_SEND_PACKETS:
1108 {
1109 /* TODO: Multipacket sends */
1110 GenericInfo.Ulong = 1;
1111 break;
1112 }
1113
1114 case OID_GEN_VENDOR_DRIVER_VERSION:
1115 {
1116 /* 1.0.0 */
1117 GenericInfo.Ulong = 0x100;
1118 break;
1119 }
1120
1121 case OID_GEN_XMIT_OK:
1122 case OID_GEN_RCV_OK:
1123 case OID_GEN_XMIT_ERROR:
1124 case OID_GEN_RCV_ERROR:
1125 case OID_GEN_RCV_NO_BUFFER:
1126 case OID_GEN_DIRECTED_FRAMES_RCV:
1127 case OID_GEN_RCV_CRC_ERROR:
1128 case OID_802_3_RCV_ERROR_ALIGNMENT:
1129 case OID_802_3_XMIT_ONE_COLLISION:
1130 case OID_802_3_XMIT_MORE_COLLISIONS:
1131 case OID_802_3_XMIT_DEFERRED:
1132 case OID_802_3_XMIT_MAX_COLLISIONS:
1133 case OID_802_3_RCV_OVERRUN:
1134 case OID_802_3_XMIT_UNDERRUN:
1135 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
1136 case OID_802_3_XMIT_TIMES_CRS_LOST:
1137 case OID_802_3_XMIT_LATE_COLLISIONS:
1138 {
1139 if (Adapter->Features & DEV_HAS_STATISTICS_COUNTERS)
1140 {
1141 NvNetReadStatistics(Adapter);
1142 NvNetQueryHwCounter(Adapter, Oid, &GenericInfo.Ulong64);
1143 }
1144 else
1145 {
1146 NvNetQuerySoftwareCounter(Adapter, Oid, &GenericInfo.Ulong64);
1147 }
1148
1149 *BytesNeeded = sizeof(ULONG64);
1150 if (InformationBufferLength < sizeof(ULONG))
1151 {
1152 *BytesWritten = 0;
1153 return NDIS_STATUS_BUFFER_TOO_SHORT;
1154 }
1155 if (InformationBufferLength >= sizeof(ULONG64))
1156 {
1157 *BytesWritten = sizeof(ULONG64);
1158 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG64));
1159 }
1160 else
1161 {
1162 *BytesWritten = sizeof(ULONG);
1163 NdisMoveMemory(InformationBuffer, InfoPtr, sizeof(ULONG));
1164 }
1165
1166 return NDIS_STATUS_SUCCESS;
1167 }
1168
1169 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
1170 {
1171 GenericInfo.Ulong = NVNET_TRANSMIT_BLOCKS - Adapter->Send.TcbSlots;
1172 break;
1173 }
1174
1175 case OID_802_3_PERMANENT_ADDRESS:
1176 {
1177 InfoPtr = Adapter->PermanentMacAddress;
1178 InfoLength = ETH_LENGTH_OF_ADDRESS;
1179 break;
1180 }
1181
1182 case OID_802_3_CURRENT_ADDRESS:
1183 {
1184 InfoPtr = Adapter->CurrentMacAddress;
1185 InfoLength = ETH_LENGTH_OF_ADDRESS;
1186 break;
1187 }
1188
1189 case OID_802_3_MULTICAST_LIST:
1190 {
1191 InfoPtr = Adapter->MulticastList;
1192 InfoLength = Adapter->MulticastListSize * ETH_LENGTH_OF_ADDRESS;
1193 break;
1194 }
1195
1196 case OID_802_3_MAXIMUM_LIST_SIZE:
1197 {
1198 GenericInfo.Ulong = NVNET_MULTICAST_LIST_SIZE;
1199 break;
1200 }
1201
1202 case OID_TCP_TASK_OFFLOAD:
1203 {
1204 return NvNetGetTcpTaskOffload(Adapter,
1205 InformationBuffer,
1206 InformationBufferLength,
1207 BytesWritten,
1208 BytesWritten);
1209 }
1210
1211 case OID_PNP_ENABLE_WAKE_UP:
1212 {
1213 GenericInfo.Ulong = NvNetGetWakeUp(Adapter);
1214 break;
1215 }
1216
1217 case OID_PNP_CAPABILITIES:
1218 {
1219 InfoLength = sizeof(NDIS_PNP_CAPABILITIES);
1220
1221 if (InformationBufferLength < InfoLength)
1222 {
1223 *BytesWritten = 0;
1224 *BytesNeeded = InfoLength;
1225 return NDIS_STATUS_BUFFER_TOO_SHORT;
1226 }
1227
1228 *BytesWritten = InfoLength;
1229 *BytesNeeded = 0;
1230 return NvNetFillPowerManagementCapabilities(Adapter, InformationBuffer);
1231 }
1232
1233 case OID_PNP_QUERY_POWER:
1234 {
1235 return NDIS_STATUS_SUCCESS;
1236 }
1237
1238 case OID_GEN_VLAN_ID:
1239 {
1240 /* TODO: Implement software VLAN support */
1241 if (!(Adapter->Flags & NV_VLAN_TAGGING))
1242 {
1243 Status = NDIS_STATUS_NOT_SUPPORTED;
1244 break;
1245 }
1246
1247 GenericInfo.Ulong = Adapter->VlanId;
1248 break;
1249 }
1250
1251 default:
1252 Status = NDIS_STATUS_INVALID_OID;
1253 break;
1254 }
1255
1256 if (Status == NDIS_STATUS_SUCCESS)
1257 {
1258 if (InfoLength > InformationBufferLength)
1259 {
1260 *BytesWritten = 0;
1261 *BytesNeeded = InfoLength;
1262 Status = NDIS_STATUS_BUFFER_TOO_SHORT;
1263 }
1264 else
1265 {
1266 NdisMoveMemory(InformationBuffer, InfoPtr, InfoLength);
1267 *BytesWritten = InfoLength;
1268 *BytesNeeded = 0;
1269 }
1270 }
1271 else
1272 {
1273 *BytesWritten = 0;
1274 *BytesNeeded = 0;
1275 }
1276
1277 return Status;
1278 }
1279
1280 NDIS_STATUS
1281 NTAPI
MiniportSetInformation(_In_ NDIS_HANDLE MiniportAdapterContext,_In_ NDIS_OID Oid,_In_ PVOID InformationBuffer,_In_ ULONG InformationBufferLength,_Out_ PULONG BytesRead,_Out_ PULONG BytesNeeded)1282 MiniportSetInformation(
1283 _In_ NDIS_HANDLE MiniportAdapterContext,
1284 _In_ NDIS_OID Oid,
1285 _In_ PVOID InformationBuffer,
1286 _In_ ULONG InformationBufferLength,
1287 _Out_ PULONG BytesRead,
1288 _Out_ PULONG BytesNeeded)
1289 {
1290 PNVNET_ADAPTER Adapter = (PNVNET_ADAPTER)MiniportAdapterContext;
1291 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1292 ULONG GenericUlong;
1293
1294 *BytesRead = 0;
1295 *BytesNeeded = 0;
1296
1297 switch (Oid)
1298 {
1299 case OID_802_3_MULTICAST_LIST:
1300 {
1301 if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS)
1302 {
1303 *BytesNeeded = (InformationBufferLength / ETH_LENGTH_OF_ADDRESS) *
1304 ETH_LENGTH_OF_ADDRESS;
1305 Status = NDIS_STATUS_INVALID_LENGTH;
1306 break;
1307 }
1308
1309 if (InformationBufferLength > sizeof(Adapter->MulticastList))
1310 {
1311 *BytesNeeded = sizeof(Adapter->MulticastList);
1312 Status = NDIS_STATUS_MULTICAST_FULL;
1313 break;
1314 }
1315
1316 *BytesRead = InformationBufferLength;
1317 NdisMoveMemory(Adapter->MulticastList, InformationBuffer, InformationBufferLength);
1318
1319 Adapter->MulticastListSize = InformationBufferLength / ETH_LENGTH_OF_ADDRESS;
1320
1321 NvNetApplyPacketFilter(Adapter);
1322 break;
1323 }
1324
1325 case OID_GEN_CURRENT_PACKET_FILTER:
1326 {
1327 if (InformationBufferLength < sizeof(ULONG))
1328 {
1329 *BytesNeeded = sizeof(ULONG);
1330 Status = NDIS_STATUS_INVALID_LENGTH;
1331 break;
1332 }
1333
1334 *BytesRead = sizeof(ULONG);
1335 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
1336
1337 if (GenericUlong & ~NVNET_PACKET_FILTERS)
1338 {
1339 Status = NDIS_STATUS_NOT_SUPPORTED;
1340 break;
1341 }
1342
1343 /* Do not check to see if the filter is the same filter */
1344 Adapter->PacketFilter = GenericUlong;
1345
1346 NvNetApplyPacketFilter(Adapter);
1347 break;
1348 }
1349
1350 case OID_GEN_CURRENT_LOOKAHEAD:
1351 {
1352 if (InformationBufferLength < sizeof(ULONG))
1353 {
1354 *BytesNeeded = sizeof(ULONG);
1355 Status = NDIS_STATUS_INVALID_LENGTH;
1356 break;
1357 }
1358
1359 /* Nothing to do */
1360 *BytesRead = sizeof(ULONG);
1361 break;
1362 }
1363
1364 case OID_GEN_VLAN_ID:
1365 {
1366 if (InformationBufferLength < sizeof(ULONG))
1367 {
1368 *BytesNeeded = sizeof(ULONG);
1369 Status = NDIS_STATUS_INVALID_LENGTH;
1370 break;
1371 }
1372
1373 if (!(Adapter->Flags & NV_VLAN_TAGGING))
1374 {
1375 Status = NDIS_STATUS_NOT_SUPPORTED;
1376 break;
1377 }
1378
1379 *BytesRead = sizeof(ULONG);
1380 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
1381
1382 if (GenericUlong > NVNET_MAXIMUM_VLAN_ID)
1383 {
1384 Status = NDIS_STATUS_FAILURE;
1385 break;
1386 }
1387
1388 Adapter->VlanId = GenericUlong;
1389 break;
1390 }
1391
1392 case OID_TCP_TASK_OFFLOAD:
1393 {
1394 if (InformationBufferLength < sizeof(NDIS_TASK_OFFLOAD_HEADER))
1395 {
1396 *BytesNeeded = sizeof(NDIS_TASK_OFFLOAD_HEADER);
1397 Status = NDIS_STATUS_INVALID_LENGTH;
1398 break;
1399 }
1400
1401 *BytesRead = InformationBufferLength;
1402
1403 Status = NvNetSetTcpTaskOffload(Adapter, InformationBuffer, BytesRead);
1404 break;
1405 }
1406
1407 case OID_PNP_ADD_WAKE_UP_PATTERN:
1408 {
1409 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
1410 {
1411 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
1412 Status = NDIS_STATUS_INVALID_LENGTH;
1413 break;
1414 }
1415
1416 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN);
1417
1418 Status = NvNetAddWakeUpPattern(Adapter, InformationBuffer);
1419 break;
1420 }
1421
1422 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
1423 {
1424 if (InformationBufferLength < sizeof(NDIS_PM_PACKET_PATTERN))
1425 {
1426 *BytesNeeded = sizeof(NDIS_PM_PACKET_PATTERN);
1427 Status = NDIS_STATUS_INVALID_LENGTH;
1428 break;
1429 }
1430
1431 *BytesRead = sizeof(NDIS_PM_PACKET_PATTERN);
1432
1433 Status = NvNetRemoveWakeUpPattern(Adapter, InformationBuffer);
1434 break;
1435 }
1436
1437 case OID_PNP_ENABLE_WAKE_UP:
1438 {
1439 if (InformationBufferLength < sizeof(ULONG))
1440 {
1441 *BytesNeeded = sizeof(ULONG);
1442 Status = NDIS_STATUS_INVALID_LENGTH;
1443 break;
1444 }
1445
1446 *BytesRead = sizeof(ULONG);
1447 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
1448
1449 NvNetEnableWakeUp(Adapter, GenericUlong);
1450 break;
1451 }
1452
1453 case OID_PNP_SET_POWER:
1454 {
1455 if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
1456 {
1457 *BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
1458 Status = NDIS_STATUS_INVALID_LENGTH;
1459 break;
1460 }
1461
1462 *BytesRead = sizeof(ULONG);
1463 NdisMoveMemory(&GenericUlong, InformationBuffer, sizeof(ULONG));
1464
1465 if (GenericUlong < NdisDeviceStateD0 || GenericUlong > NdisDeviceStateD3)
1466 {
1467 Status = NDIS_STATUS_INVALID_DATA;
1468 break;
1469 }
1470
1471 Status = NvNetSetPower(Adapter, GenericUlong);
1472 break;
1473 }
1474
1475 default:
1476 Status = NDIS_STATUS_NOT_SUPPORTED;
1477 break;
1478 }
1479
1480 return Status;
1481 }
1482