ReactOS 0.4.15-dev-7958-gcd0bb1a
ParaNdis-Common.c
Go to the documentation of this file.
1/*
2 * This file contains NDIS driver procedures, common for NDIS5 and NDIS6
3 *
4 * Copyright (c) 2008-2017 Red Hat, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met :
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and / or other materials provided with the distribution.
14 * 3. Neither the names of the copyright holders nor the names of their contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29#include "ndis56common.h"
30
31#ifdef WPP_EVENT_TRACING
32#include "ParaNdis-Common.tmh"
33#endif
34
35static void ReuseReceiveBufferRegular(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor);
36static void ReuseReceiveBufferPowerOff(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor);
37
38//#define ROUNDSIZE(sz) ((sz + 15) & ~15)
39#define MAX_VLAN_ID 4095
40
41#if 0
43{
44 PUCHAR peth = (PUCHAR)header;
45 DPrintf(level, ("[%s] %02X%02X%02X%02X%02X%02X => %02X%02X%02X%02X%02X%02X", prefix,
46 peth[6], peth[7], peth[8], peth[9], peth[10], peth[11],
47 peth[0], peth[1], peth[2], peth[3], peth[4], peth[5]));
48}
49#else
51{
52}
53#endif
54
55
56
57/**********************************************************
58Validates MAC address
59Valid MAC address is not broadcast, not multicast, not empty
60if bLocal is set, it must be LOCAL
61if not, is must be non-local or local
62Parameters:
63 PUCHAR pcMacAddress - MAC address to validate
64 BOOLEAN bLocal - TRUE, if we validate locally administered address
65Return value:
66 TRUE if valid
67***********************************************************/
69{
70 BOOLEAN bLA = FALSE, bEmpty, bBroadcast, bMulticast = FALSE;
71 bBroadcast = ETH_IS_BROADCAST(pcMacAddress);
72 bLA = !bBroadcast && ETH_IS_LOCALLY_ADMINISTERED(pcMacAddress);
73 bMulticast = !bBroadcast && ETH_IS_MULTICAST(pcMacAddress);
74 bEmpty = ETH_IS_EMPTY(pcMacAddress);
75 return !bBroadcast && !bEmpty && !bMulticast && (!bLocal || bLA);
76}
77
79{
81 return iptBroadcast;
83 return iptMulticast;
84 return iptUnicast;
85}
86
88{
89 const char *Name;
94
96{
132
134{
135 { "Promiscuous", 0, 0, 1 },
136 { "Priority", 0, 0, 1 },
137 { "ConnectRate", 100,10,10000 },
138 { "DoLog", 1, 0, 1 },
139 { "DebugLevel", 2, 0, 8 },
140 { "ConnectTimer", 0, 0, 300000 },
141 { "DpcCheck", 0, 0, 2 },
142 { "TxCapacity", 1024, 16, 1024 },
143 { "RxCapacity", 256, 32, 1024 },
144 { "InterruptRecovery", 0, 0, 1},
145 { "LogStatistics", 0, 0, 10000},
146 { "PacketFilter", 1, 0, 1},
147 { "Gather", 1, 0, 1},
148 { "BatchReceive", 1, 0, 1},
149 { "Offload.TxChecksum", 0, 0, 31},
150 { "Offload.TxLSO", 0, 0, 2},
151 { "Offload.RxCS", 0, 0, 31},
152 { "Offload.GuestCS", 0, 0, 1},
153 { "UseSwTxChecksum", 0, 0, 1 },
154 { "IPPacketsCheck", 0, 0, 3 },
155 { "*IPChecksumOffloadIPv4", 3, 0, 3 },
156 { "*TCPChecksumOffloadIPv4",3, 0, 3 },
157 { "*TCPChecksumOffloadIPv6",3, 0, 3 },
158 { "*UDPChecksumOffloadIPv4",3, 0, 3 },
159 { "*UDPChecksumOffloadIPv6",3, 0, 3 },
160 { "*LsoV1IPv4", 1, 0, 1 },
161 { "*LsoV2IPv4", 1, 0, 1 },
162 { "*LsoV2IPv6", 1, 0, 1 },
163 { "*PriorityVLANTag", 3, 0, 3},
164 { "VlanId", 0, 0, MAX_VLAN_ID},
165 { "MergeableBuf", 1, 0, 1},
166 { "MTU", 1500, 500, 65500},
167 { "NumberOfHandledRXPackersInDPC", MAX_RX_LOOPS, 1, 10000},
168 { "Indirect", 0, 0, 2},
169};
170
172{
173 virtio_device_reset(&pContext->IODevice);
174 DPrintf(0, ("[%s] Done", __FUNCTION__));
175 /* reset all the features in the device */
176 pContext->ulCurrentVlansFilterSet = 0;
177 pContext->ullGuestFeatures = 0;
178#ifdef VIRTIO_RESET_VERIFY
179 if (1)
180 {
181 u8 devStatus;
182 devStatus = virtio_get_status(&pContext->IODevice);
183 if (devStatus)
184 {
185 DPrintf(0, ("[%s] Device status is still %02X", __FUNCTION__, (ULONG)devStatus));
186 virtio_device_reset(&pContext->IODevice);
187 devStatus = virtio_get_status(&pContext->IODevice);
188 DPrintf(0, ("[%s] Device status on retry %02X", __FUNCTION__, (ULONG)devStatus));
189 }
190 }
191#endif
192}
193
194/**********************************************************
195Gets integer value for specifies in pEntry->Name name
196Parameters:
197 NDIS_HANDLE cfg previously open configuration
198 tConfigurationEntry *pEntry - Entry to fill value in
199***********************************************************/
201{
203 const char *statusName;
204 NDIS_STRING name = {0};
209 &status,
210 &pParam,
211 cfg,
212 &name,
215 {
216 ULONG ulValue = pParam->ParameterData.IntegerData;
217 if (ulValue >= pEntry->ulMinimal && ulValue <= pEntry->ulMaximal)
218 {
219 pEntry->ulValue = ulValue;
220 statusName = "value";
221 }
222 else
223 {
224 statusName = "out of range";
225 }
226 }
227 else
228 {
229 statusName = "nothing";
230 }
231 DPrintf(2, ("[%s] %s read for %s - 0x%x",
233 statusName,
234 pEntry->Name,
235 pEntry->ulValue));
236 if (name.Buffer) NdisFreeString(name);
237}
238
240{
241 if (pContext->Offload.flagsValue & osbT4Lso)
242 {
243 DPrintf(0, ("[%s] Warning: %s", procname, reason));
244 pContext->Offload.flagsValue &= ~osbT4Lso;
246 }
247}
248
250{
251 if (pContext->Offload.flagsValue & osbT6Lso)
252 {
253 DPrintf(0, ("[%s] Warning: %s", procname, reason));
254 pContext->Offload.flagsValue &= ~osbT6Lso;
256 }
257}
258
260{
261 if (pContext->Offload.flagsValue & (osbT4Lso | osbT6Lso))
262 {
263 DPrintf(0, ("[%s] Warning: %s", procname, reason));
264 pContext->Offload.flagsValue &= ~(osbT6Lso | osbT4Lso);
266 }
267}
268
269/**********************************************************
270Loads NIC parameters from adapter registry key
271Parameters:
272 context
273 PUCHAR *ppNewMACAddress - pointer to hold MAC address if configured from host
274***********************************************************/
275static void ReadNicConfiguration(PARANDIS_ADAPTER *pContext, PUCHAR *ppNewMACAddress)
276{
277 NDIS_HANDLE cfg;
279 if (pConfiguration)
280 {
282 cfg = ParaNdis_OpenNICConfiguration(pContext);
283 if (cfg)
284 {
285 GetConfigurationEntry(cfg, &pConfiguration->isLogEnabled);
286 GetConfigurationEntry(cfg, &pConfiguration->debugLevel);
287 GetConfigurationEntry(cfg, &pConfiguration->ConnectRate);
288 GetConfigurationEntry(cfg, &pConfiguration->PrioritySupport);
289 GetConfigurationEntry(cfg, &pConfiguration->isPromiscuous);
290 GetConfigurationEntry(cfg, &pConfiguration->TxCapacity);
291 GetConfigurationEntry(cfg, &pConfiguration->RxCapacity);
292 GetConfigurationEntry(cfg, &pConfiguration->connectTimer);
293 GetConfigurationEntry(cfg, &pConfiguration->dpcChecker);
294 GetConfigurationEntry(cfg, &pConfiguration->InterruptRecovery);
295 GetConfigurationEntry(cfg, &pConfiguration->LogStatistics);
296 GetConfigurationEntry(cfg, &pConfiguration->PacketFiltering);
297 GetConfigurationEntry(cfg, &pConfiguration->ScatterGather);
298 GetConfigurationEntry(cfg, &pConfiguration->BatchReceive);
299 GetConfigurationEntry(cfg, &pConfiguration->OffloadTxChecksum);
300 GetConfigurationEntry(cfg, &pConfiguration->OffloadTxLSO);
301 GetConfigurationEntry(cfg, &pConfiguration->OffloadRxCS);
302 GetConfigurationEntry(cfg, &pConfiguration->OffloadGuestCS);
303 GetConfigurationEntry(cfg, &pConfiguration->UseSwTxChecksum);
304 GetConfigurationEntry(cfg, &pConfiguration->IPPacketsCheck);
305 GetConfigurationEntry(cfg, &pConfiguration->stdIpcsV4);
306 GetConfigurationEntry(cfg, &pConfiguration->stdTcpcsV4);
307 GetConfigurationEntry(cfg, &pConfiguration->stdTcpcsV6);
308 GetConfigurationEntry(cfg, &pConfiguration->stdUdpcsV4);
309 GetConfigurationEntry(cfg, &pConfiguration->stdUdpcsV6);
310 GetConfigurationEntry(cfg, &pConfiguration->stdLsoV1);
311 GetConfigurationEntry(cfg, &pConfiguration->stdLsoV2ip4);
312 GetConfigurationEntry(cfg, &pConfiguration->stdLsoV2ip6);
313 GetConfigurationEntry(cfg, &pConfiguration->PriorityVlanTagging);
315 GetConfigurationEntry(cfg, &pConfiguration->UseMergeableBuffers);
317 GetConfigurationEntry(cfg, &pConfiguration->NumberOfHandledRXPackersInDPC);
318 GetConfigurationEntry(cfg, &pConfiguration->Indirect);
319
320 #if !defined(WPP_EVENT_TRACING)
321 bDebugPrint = pConfiguration->isLogEnabled.ulValue;
322 nDebugLevel = pConfiguration->debugLevel.ulValue;
323 #endif
324 // ignoring promiscuous setting, nothing to do with it
325 pContext->maxFreeTxDescriptors = pConfiguration->TxCapacity.ulValue;
326 pContext->NetMaxReceiveBuffers = pConfiguration->RxCapacity.ulValue;
327 pContext->ulMilliesToConnect = pConfiguration->connectTimer.ulValue;
328 pContext->nEnableDPCChecker = pConfiguration->dpcChecker.ulValue;
329 pContext->bDoInterruptRecovery = pConfiguration->InterruptRecovery.ulValue != 0;
330 pContext->Limits.nPrintDiagnostic = pConfiguration->LogStatistics.ulValue;
331 pContext->uNumberOfHandledRXPacketsInDPC = pConfiguration->NumberOfHandledRXPackersInDPC.ulValue;
332 pContext->bDoSupportPriority = pConfiguration->PrioritySupport.ulValue != 0;
333 pContext->ulFormalLinkSpeed = pConfiguration->ConnectRate.ulValue;
334 pContext->ulFormalLinkSpeed *= 1000000;
335 pContext->bDoHwPacketFiltering = pConfiguration->PacketFiltering.ulValue != 0;
336 pContext->bUseScatterGather = pConfiguration->ScatterGather.ulValue != 0;
337 pContext->bBatchReceive = pConfiguration->BatchReceive.ulValue != 0;
338 pContext->bDoHardwareChecksum = pConfiguration->UseSwTxChecksum.ulValue == 0;
339 pContext->bDoGuestChecksumOnReceive = pConfiguration->OffloadGuestCS.ulValue != 0;
340 pContext->bDoIPCheckTx = pConfiguration->IPPacketsCheck.ulValue & 1;
341 pContext->bDoIPCheckRx = pConfiguration->IPPacketsCheck.ulValue & 2;
342 pContext->Offload.flagsValue = 0;
343 // TX caps: 1 - TCP, 2 - UDP, 4 - IP, 8 - TCPv6, 16 - UDPv6
344 if (pConfiguration->OffloadTxChecksum.ulValue & 1) pContext->Offload.flagsValue |= osbT4TcpChecksum | osbT4TcpOptionsChecksum;
345 if (pConfiguration->OffloadTxChecksum.ulValue & 2) pContext->Offload.flagsValue |= osbT4UdpChecksum;
346 if (pConfiguration->OffloadTxChecksum.ulValue & 4) pContext->Offload.flagsValue |= osbT4IpChecksum | osbT4IpOptionsChecksum;
347 if (pConfiguration->OffloadTxChecksum.ulValue & 8) pContext->Offload.flagsValue |= osbT6TcpChecksum | osbT6TcpOptionsChecksum;
348 if (pConfiguration->OffloadTxChecksum.ulValue & 16) pContext->Offload.flagsValue |= osbT6UdpChecksum;
349 if (pConfiguration->OffloadTxLSO.ulValue) pContext->Offload.flagsValue |= osbT4Lso | osbT4LsoIp | osbT4LsoTcp;
350 if (pConfiguration->OffloadTxLSO.ulValue > 1) pContext->Offload.flagsValue |= osbT6Lso | osbT6LsoTcpOptions;
351 // RX caps: 1 - TCP, 2 - UDP, 4 - IP, 8 - TCPv6, 16 - UDPv6
352 if (pConfiguration->OffloadRxCS.ulValue & 1) pContext->Offload.flagsValue |= osbT4RxTCPChecksum | osbT4RxTCPOptionsChecksum;
353 if (pConfiguration->OffloadRxCS.ulValue & 2) pContext->Offload.flagsValue |= osbT4RxUDPChecksum;
354 if (pConfiguration->OffloadRxCS.ulValue & 4) pContext->Offload.flagsValue |= osbT4RxIPChecksum | osbT4RxIPOptionsChecksum;
355 if (pConfiguration->OffloadRxCS.ulValue & 8) pContext->Offload.flagsValue |= osbT6RxTCPChecksum | osbT6RxTCPOptionsChecksum;
356 if (pConfiguration->OffloadRxCS.ulValue & 16) pContext->Offload.flagsValue |= osbT6RxUDPChecksum;
357 /* full packet size that can be configured as GSO for VIRTIO is short */
358 /* NDIS test fails sometimes fails on segments 50-60K */
360 pContext->InitialOffloadParameters.IPv4Checksum = (UCHAR)pConfiguration->stdIpcsV4.ulValue;
361 pContext->InitialOffloadParameters.TCPIPv4Checksum = (UCHAR)pConfiguration->stdTcpcsV4.ulValue;
362 pContext->InitialOffloadParameters.TCPIPv6Checksum = (UCHAR)pConfiguration->stdTcpcsV6.ulValue;
363 pContext->InitialOffloadParameters.UDPIPv4Checksum = (UCHAR)pConfiguration->stdUdpcsV4.ulValue;
364 pContext->InitialOffloadParameters.UDPIPv6Checksum = (UCHAR)pConfiguration->stdUdpcsV6.ulValue;
365 pContext->InitialOffloadParameters.LsoV1 = (UCHAR)pConfiguration->stdLsoV1.ulValue;
366 pContext->InitialOffloadParameters.LsoV2IPv4 = (UCHAR)pConfiguration->stdLsoV2ip4.ulValue;
367 pContext->InitialOffloadParameters.LsoV2IPv6 = (UCHAR)pConfiguration->stdLsoV2ip6.ulValue;
368 pContext->ulPriorityVlanSetting = pConfiguration->PriorityVlanTagging.ulValue;
369 pContext->VlanId = pConfiguration->VlanId.ulValue & 0xfff;
370 pContext->bUseMergedBuffers = pConfiguration->UseMergeableBuffers.ulValue != 0;
371 pContext->MaxPacketSize.nMaxDataSize = pConfiguration->MTU.ulValue;
372 pContext->bUseIndirect = pConfiguration->Indirect.ulValue != 0;
373 if (!pContext->bDoSupportPriority)
374 pContext->ulPriorityVlanSetting = 0;
375 // if Vlan not supported
376 if (!IsVlanSupported(pContext))
377 pContext->VlanId = 0;
378 if (1)
379 {
381 PVOID p;
382 UINT len = 0;
384 if (status == NDIS_STATUS_SUCCESS && len == sizeof(pContext->CurrentMacAddress))
385 {
386 *ppNewMACAddress = ParaNdis_AllocateMemory(pContext, sizeof(pContext->CurrentMacAddress));
387 if (*ppNewMACAddress)
388 {
389 NdisMoveMemory(*ppNewMACAddress, p, len);
390 }
391 else
392 {
393 DPrintf(0, ("[%s] MAC address present, but some problem also...", __FUNCTION__));
394 }
395 }
396 else if (len && len != sizeof(pContext->CurrentMacAddress))
397 {
398 DPrintf(0, ("[%s] MAC address has wrong length of %d", __FUNCTION__, len));
399 }
400 else
401 {
402 DPrintf(4, ("[%s] Nothing read for MAC, error %X", __FUNCTION__, status));
403 }
404 }
406 }
408 }
409}
410
412{
413 if (!pDest) pDest = &pContext->Offload.flags;
414 if (!from) from = &pContext->Offload.flagsValue;
415
416 pDest->fTxIPChecksum = !!(*from & osbT4IpChecksum);
417 pDest->fTxTCPChecksum = !!(*from & osbT4TcpChecksum);
418 pDest->fTxUDPChecksum = !!(*from & osbT4UdpChecksum);
421
422 pDest->fTxLso = !!(*from & osbT4Lso);
423 pDest->fTxLsoIP = !!(*from & osbT4LsoIp);
424 pDest->fTxLsoTCP = !!(*from & osbT4LsoTcp);
425
426 pDest->fRxIPChecksum = !!(*from & osbT4RxIPChecksum);
428 pDest->fRxTCPChecksum = !!(*from & osbT4RxTCPChecksum);
430 pDest->fRxUDPChecksum = !!(*from & osbT4RxUDPChecksum);
431
432 pDest->fTxTCPv6Checksum = !!(*from & osbT6TcpChecksum);
434 pDest->fTxUDPv6Checksum = !!(*from & osbT6UdpChecksum);
435 pDest->fTxIPv6Ext = !!(*from & osbT6IpExtChecksum);
436
437 pDest->fTxLsov6 = !!(*from & osbT6Lso);
438 pDest->fTxLsov6IP = !!(*from & osbT6LsoIpExt);
439 pDest->fTxLsov6TCP = !!(*from & osbT6LsoTcpOptions);
440
444 pDest->fRxIPv6Ext = !!(*from & osbT6RxIpExtChecksum);
445}
446
447/**********************************************************
448Enumerates adapter resources and fills the structure holding them
449Verifies that IO assigned and has correct size
450Verifies that interrupt assigned
451Parameters:
452 PNDIS_RESOURCE_LIST RList - list of resources, received from NDIS
453 tAdapterResources *pResources - structure to fill
454Return value:
455 TRUE if everything is OK
456***********************************************************/
458{
459 UINT i;
460 int read, bar = -1;
461 PCI_COMMON_HEADER pci_config;
462 NdisZeroMemory(pResources, sizeof(*pResources));
463
464 // read the PCI config space header
466 MiniportHandle,
467 0 /* SlotNumber, reserved */,
468 0 /* Offset */,
469 &pci_config,
470 sizeof(pci_config));
471 if (read != sizeof(pci_config)) {
472 return FALSE;
473 }
474
475 for (i = 0; i < RList->Count; ++i)
476 {
479 {
481 ULONG len = RList->PartialDescriptors[i].u.Port.Length;
482 DPrintf(0, ("Found IO ports at %08lX(%d)", Start.LowPart, len));
483 bar = virtio_get_bar_index(&pci_config, Start);
484 if (bar < 0) {
485 break;
486 }
487 pResources->PciBars[bar].BasePA = Start;
488 pResources->PciBars[bar].uLength = len;
489 pResources->PciBars[bar].bPortSpace = TRUE;
490 }
491 else if (type == CmResourceTypeMemory)
492 {
494 ULONG len = RList->PartialDescriptors[i].u.Memory.Length;
495 DPrintf(0, ("Found IO memory at %08I64X(%d)", Start.QuadPart, len));
496 bar = virtio_get_bar_index(&pci_config, Start);
497 if (bar < 0) {
498 break;
499 }
500 pResources->PciBars[bar].BasePA = Start;
501 pResources->PciBars[bar].uLength = len;
502 pResources->PciBars[bar].bPortSpace = FALSE;
503 }
504 else if (type == CmResourceTypeInterrupt)
505 {
506 pResources->Vector = RList->PartialDescriptors[i].u.Interrupt.Vector;
507 pResources->Level = RList->PartialDescriptors[i].u.Interrupt.Level;
508 pResources->Affinity = RList->PartialDescriptors[i].u.Interrupt.Affinity;
509 pResources->InterruptFlags = RList->PartialDescriptors[i].Flags;
510 DPrintf(0, ("Found Interrupt vector %d, level %d, affinity %X, flags %X",
511 pResources->Vector, pResources->Level, (ULONG)pResources->Affinity, pResources->InterruptFlags));
512 }
513 }
514 return bar >= 0 && pResources->Vector;
515}
516
518{
519 const struct { ULONG bitmask; const PCHAR Name; } Features[] =
520 {
521
522 {VIRTIO_NET_F_CSUM, "VIRTIO_NET_F_CSUM" },
523 {VIRTIO_NET_F_GUEST_CSUM, "VIRTIO_NET_F_GUEST_CSUM" },
524 {VIRTIO_NET_F_MAC, "VIRTIO_NET_F_MAC" },
525 {VIRTIO_NET_F_GSO, "VIRTIO_NET_F_GSO" },
526 {VIRTIO_NET_F_GUEST_TSO4, "VIRTIO_NET_F_GUEST_TSO4"},
527 {VIRTIO_NET_F_GUEST_TSO6, "VIRTIO_NET_F_GUEST_TSO6"},
528 {VIRTIO_NET_F_GUEST_ECN, "VIRTIO_NET_F_GUEST_ECN"},
529 {VIRTIO_NET_F_GUEST_UFO, "VIRTIO_NET_F_GUEST_UFO"},
530 {VIRTIO_NET_F_HOST_TSO4, "VIRTIO_NET_F_HOST_TSO4"},
531 {VIRTIO_NET_F_HOST_TSO6, "VIRTIO_NET_F_HOST_TSO6"},
532 {VIRTIO_NET_F_HOST_ECN, "VIRTIO_NET_F_HOST_ECN"},
533 {VIRTIO_NET_F_HOST_UFO, "VIRTIO_NET_F_HOST_UFO"},
534 {VIRTIO_NET_F_MRG_RXBUF, "VIRTIO_NET_F_MRG_RXBUF"},
535 {VIRTIO_NET_F_STATUS, "VIRTIO_NET_F_STATUS"},
536 {VIRTIO_NET_F_CTRL_VQ, "VIRTIO_NET_F_CTRL_VQ"},
537 {VIRTIO_NET_F_CTRL_RX, "VIRTIO_NET_F_CTRL_RX"},
538 {VIRTIO_NET_F_CTRL_VLAN, "VIRTIO_NET_F_CTRL_VLAN"},
539 {VIRTIO_NET_F_CTRL_RX_EXTRA, "VIRTIO_NET_F_CTRL_RX_EXTRA"},
540 {VIRTIO_RING_F_INDIRECT_DESC, "VIRTIO_RING_F_INDIRECT_DESC"},
541 {VIRTIO_F_VERSION_1, "VIRTIO_F_VERSION_1" },
542 {VIRTIO_F_ANY_LAYOUT, "VIRTIO_F_ANY_LAYOUT" },
543 };
544 UINT i;
545 for (i = 0; i < sizeof(Features)/sizeof(Features[0]); ++i)
546 {
547 if (VirtIODeviceGetHostFeature(pContext, Features[i].bitmask))
548 {
549 DPrintf(0, ("VirtIO Host Feature %s", Features[i].Name));
550 }
551 }
552}
553
554/**********************************************************
555 Only for test. Prints out if the interrupt line is ON
556Parameters:
557Return value:
558***********************************************************/
559static void JustForCheckClearInterrupt(PARANDIS_ADAPTER *pContext, const char *Label)
560{
561 if (pContext->bEnableInterruptChecking)
562 {
563 ULONG ulActive;
564 ulActive = virtio_read_isr_status(&pContext->IODevice);
565 if (ulActive)
566 {
567 DPrintf(0,("WARNING: Interrupt Line %d(%s)!", ulActive, Label));
568 }
569 }
570}
571
572/**********************************************************
573Prints out statistics
574***********************************************************/
575static void PrintStatistics(PARANDIS_ADAPTER *pContext)
576{
577 ULONG64 totalTxFrames =
581 ULONG64 totalRxFrames =
584 pContext->Statistics.ifHCInUcastPkts;
585
586 DPrintf(0, ("[Diag!%X] RX buffers at VIRTIO %d of %d",
587 pContext->CurrentMacAddress[5],
588 pContext->NetNofReceiveBuffers,
589 pContext->NetMaxReceiveBuffers));
590 DPrintf(0, ("[Diag!] TX desc available %d/%d, buf %d/min. %d",
591 pContext->nofFreeTxDescriptors,
592 pContext->maxFreeTxDescriptors,
593 pContext->nofFreeHardwareBuffers,
594 pContext->minFreeHardwareBuffers));
596 if (pContext->NetTxPacketsToReturn)
597 {
598 DPrintf(0, ("[Diag!] TX packets to return %d", pContext->NetTxPacketsToReturn));
599 }
600 DPrintf(0, ("[Diag!] Bytes transmitted %I64u, received %I64u",
601 pContext->Statistics.ifHCOutOctets,
602 pContext->Statistics.ifHCInOctets));
603 DPrintf(0, ("[Diag!] Tx frames %I64u, CSO %d, LSO %d, indirect %d",
604 totalTxFrames,
605 pContext->extraStatistics.framesCSOffload,
606 pContext->extraStatistics.framesLSO,
607 pContext->extraStatistics.framesIndirect));
608 DPrintf(0, ("[Diag!] Rx frames %I64u, Rx.Pri %d, RxHwCS.OK %d, FiltOut %d",
609 totalRxFrames, pContext->extraStatistics.framesRxPriority,
610 pContext->extraStatistics.framesRxCSHwOK, pContext->extraStatistics.framesFilteredOut));
611 if (pContext->extraStatistics.framesRxCSHwMissedBad || pContext->extraStatistics.framesRxCSHwMissedGood)
612 {
613 DPrintf(0, ("[Diag!] RxHwCS mistakes: missed bad %d, missed good %d",
614 pContext->extraStatistics.framesRxCSHwMissedBad, pContext->extraStatistics.framesRxCSHwMissedGood));
615 }
616}
617
619 switch (nt_status) {
620 case STATUS_SUCCESS:
621 return NDIS_STATUS_SUCCESS;
622 case STATUS_NOT_FOUND:
629 default:
630 return NDIS_STATUS_FAILURE;
631 }
632}
633
635{
636 NTSTATUS nt_status = virtio_set_features(&pContext->IODevice, pContext->ullGuestFeatures);
637 if (!NT_SUCCESS(nt_status)) {
638 DPrintf(0, ("[%s] virtio_set_features failed with %x\n", __FUNCTION__, nt_status));
639 }
640 return NTStatusToNdisStatus(nt_status);
641}
642
643/**********************************************************
644Initializes the context structure
645Major variables, received from NDIS on initialization, must be be set before this call
646(for ex. pContext->MiniportHandle)
647
648If this procedure fails, no need to call
649 ParaNdis_CleanupContext
650
651
652Parameters:
653Return value:
654 SUCCESS, if resources are OK
655 NDIS_STATUS_RESOURCE_CONFLICT if not
656***********************************************************/
658 PARANDIS_ADAPTER *pContext,
659 PNDIS_RESOURCE_LIST pResourceList)
660{
662 PUCHAR pNewMacAddress = NULL;
663 USHORT linkStatus = 0;
664 NTSTATUS nt_status;
665
666 DEBUG_ENTRY(0);
667 /* read first PCI IO bar*/
668 //ulIOAddress = ReadPCIConfiguration(miniportAdapterHandle, 0x10);
669 /* check this is IO and assigned */
670 ReadNicConfiguration(pContext, &pNewMacAddress);
671 if (pNewMacAddress)
672 {
673 if (ParaNdis_ValidateMacAddress(pNewMacAddress, TRUE))
674 {
675 DPrintf(0, ("[%s] WARNING: MAC address reloaded", __FUNCTION__));
676 NdisMoveMemory(pContext->CurrentMacAddress, pNewMacAddress, sizeof(pContext->CurrentMacAddress));
677 }
678 else
679 {
680 DPrintf(0, ("[%s] WARNING: Invalid MAC address ignored", __FUNCTION__));
681 }
682 NdisFreeMemory(pNewMacAddress, 0, 0);
683 }
684
688 if (pContext->ulPriorityVlanSetting)
690
691 if (GetAdapterResources(pContext->MiniportHandle, pResourceList, &pContext->AdapterResources))
692 {
694 {
695 DPrintf(0, ("[%s] Message interrupt assigned", __FUNCTION__));
696 pContext->bUsingMSIX = TRUE;
697 }
698
699 nt_status = virtio_device_initialize(
700 &pContext->IODevice,
702 pContext,
703 pContext->bUsingMSIX);
704 if (!NT_SUCCESS(nt_status)) {
705 DPrintf(0, ("[%s] virtio_device_initialize failed with %x\n", __FUNCTION__, nt_status));
706 status = NTStatusToNdisStatus(nt_status);
708 return status;
709 }
710
711 pContext->bIODeviceInitialized = TRUE;
712 JustForCheckClearInterrupt(pContext, "init 0");
714 JustForCheckClearInterrupt(pContext, "init 1");
716 JustForCheckClearInterrupt(pContext, "init 2");
718 pContext->ullHostFeatures = virtio_get_features(&pContext->IODevice);
719 DumpVirtIOFeatures(pContext);
720 JustForCheckClearInterrupt(pContext, "init 3");
722
723 if(pContext->bLinkDetectSupported) {
724 virtio_get_config(&pContext->IODevice, sizeof(pContext->CurrentMacAddress), &linkStatus, sizeof(linkStatus));
725 pContext->bConnected = (linkStatus & VIRTIO_NET_S_LINK_UP) != 0;
726 DPrintf(0, ("[%s] Link status on driver startup: %d", __FUNCTION__, pContext->bConnected));
727 }
728
730 {
731 // virtio 1.0 always uses the extended header
732 pContext->nVirtioHeaderSize = sizeof(virtio_net_hdr_ext);
734 }
735 else
736 {
737 pContext->nVirtioHeaderSize = sizeof(virtio_net_hdr_basic);
738 }
739
741 {
743 }
745 {
747 }
748
750 {
751 DPrintf(0, ("[%s] Not using mergeable buffers", __FUNCTION__));
752 }
753 else
754 {
756 if (pContext->bUseMergedBuffers)
757 {
758 pContext->nVirtioHeaderSize = sizeof(virtio_net_hdr_ext);
760 }
761 }
763 {
765 &pContext->IODevice,
766 0, // + offsetof(struct virtio_net_config, mac)
767 &pContext->PermanentMacAddress,
770 {
771 DPrintf(0,("Invalid device MAC ignored(%02x-%02x-%02x-%02x-%02x-%02x)",
772 pContext->PermanentMacAddress[0],
773 pContext->PermanentMacAddress[1],
774 pContext->PermanentMacAddress[2],
775 pContext->PermanentMacAddress[3],
776 pContext->PermanentMacAddress[4],
777 pContext->PermanentMacAddress[5]));
778 NdisZeroMemory(pContext->PermanentMacAddress, sizeof(pContext->PermanentMacAddress));
779 }
780 }
781
782 if (ETH_IS_EMPTY(pContext->PermanentMacAddress))
783 {
784 DPrintf(0, ("No device MAC present, use default"));
785 pContext->PermanentMacAddress[0] = 0x02;
786 pContext->PermanentMacAddress[1] = 0x50;
787 pContext->PermanentMacAddress[2] = 0xF2;
788 pContext->PermanentMacAddress[3] = 0x00;
789 pContext->PermanentMacAddress[4] = 0x01;
790 pContext->PermanentMacAddress[5] = 0x80 | (UCHAR)(pContext->ulUniqueID & 0xFF);
791 }
792 DPrintf(0,("Device MAC = %02x-%02x-%02x-%02x-%02x-%02x",
793 pContext->PermanentMacAddress[0],
794 pContext->PermanentMacAddress[1],
795 pContext->PermanentMacAddress[2],
796 pContext->PermanentMacAddress[3],
797 pContext->PermanentMacAddress[4],
798 pContext->PermanentMacAddress[5]));
799
800 if (ETH_IS_EMPTY(pContext->CurrentMacAddress))
801 {
803 &pContext->CurrentMacAddress,
804 &pContext->PermanentMacAddress,
806 }
807 else
808 {
809 DPrintf(0,("Current MAC = %02x-%02x-%02x-%02x-%02x-%02x",
810 pContext->CurrentMacAddress[0],
811 pContext->CurrentMacAddress[1],
812 pContext->CurrentMacAddress[2],
813 pContext->CurrentMacAddress[3],
814 pContext->CurrentMacAddress[4],
815 pContext->CurrentMacAddress[5]));
816 }
818 pContext->bHasControlQueue = TRUE;
820 }
821 }
822 else
823 {
824 DPrintf(0, ("[%s] Error: Incomplete resources", __FUNCTION__));
826 }
827
828
829 if (pContext->bDoHardwareChecksum)
830 {
831 ULONG dependentOptions;
834 (pContext->Offload.flagsValue & dependentOptions))
835 {
836 DPrintf(0, ("[%s] Host does not support CSUM, disabling CS offload", __FUNCTION__) );
837 pContext->Offload.flagsValue &= ~dependentOptions;
838 }
839 }
840
842 {
843 DPrintf(0, ("[%s] Enabling guest checksum", __FUNCTION__) );
845 }
846 else
847 {
849 }
850
851 // now, after we checked the capabilities, we can initialize current
852 // configuration of offload tasks
854 if (pContext->Offload.flags.fTxLso && !pContext->bUseScatterGather)
855 {
856 DisableBothLSOPermanently(pContext, __FUNCTION__, "SG is not active");
857 }
858 if (pContext->Offload.flags.fTxLso &&
860 {
861 DisableLSOv4Permanently(pContext, __FUNCTION__, "Host does not support TSOv4");
862 }
863 if (pContext->Offload.flags.fTxLsov6 &&
865 {
866 DisableLSOv6Permanently(pContext, __FUNCTION__, "Host does not support TSOv6");
867 }
868 if (pContext->bUseIndirect)
869 {
870 const char *reason = "";
872 {
873 pContext->bUseIndirect = FALSE;
874 reason = "Host support";
875 }
876 else if (!pContext->bUseScatterGather)
877 {
878 pContext->bUseIndirect = FALSE;
879 reason = "SG";
880 }
881 DPrintf(0, ("[%s] %sable indirect Tx(!%s)", __FUNCTION__, pContext->bUseIndirect ? "En" : "Dis", reason) );
882 }
883
885 pContext->bDoHwPacketFiltering)
886 {
887 DPrintf(0, ("[%s] Using hardware packet filtering", __FUNCTION__));
888 pContext->bHasHardwareFilters = TRUE;
889 }
890
891 status = FinalizeFeatures(pContext);
892
894
897 return status;
898}
899
900/**********************************************************
901Free the resources allocated for VirtIO buffer descriptor
902Parameters:
903 PVOID pParam pIONetDescriptor to free
904 BOOLEAN bRemoveFromList TRUE, if also remove it from list
905***********************************************************/
906static void VirtIONetFreeBufferDescriptor(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDescriptor)
907{
908 if(pBufferDescriptor)
909 {
910 if (pBufferDescriptor->pHolder)
911 ParaNdis_UnbindBufferFromPacket(pContext, pBufferDescriptor);
912 if (pBufferDescriptor->DataInfo.Virtual)
913 ParaNdis_FreePhysicalMemory(pContext, &pBufferDescriptor->DataInfo);
914 if (pBufferDescriptor->HeaderInfo.Virtual)
915 ParaNdis_FreePhysicalMemory(pContext, &pBufferDescriptor->HeaderInfo);
916 NdisFreeMemory(pBufferDescriptor, 0, 0);
917 }
918}
919
920/**********************************************************
921Free all the buffer descriptors from specified list
922Parameters:
923 PLIST_ENTRY pListRoot list containing pIONetDescriptor structures
924 PNDIS_SPIN_LOCK pLock lock to protest this list
925Return value:
926***********************************************************/
928{
929 pIONetDescriptor pBufferDescriptor;
930 LIST_ENTRY TempList;
931 InitializeListHead(&TempList);
933 while(!IsListEmpty(pListRoot))
934 {
935 pBufferDescriptor = (pIONetDescriptor)RemoveHeadList(pListRoot);
936 InsertTailList(&TempList, &pBufferDescriptor->listEntry);
937 }
939 while(!IsListEmpty(&TempList))
940 {
941 pBufferDescriptor = (pIONetDescriptor)RemoveHeadList(&TempList);
942 VirtIONetFreeBufferDescriptor(pContext, pBufferDescriptor);
943 }
944}
945
947 PARANDIS_ADAPTER *pContext,
948 ULONG size1,
949 ULONG size2,
950 BOOLEAN bForTx)
951{
953 p = (pIONetDescriptor)ParaNdis_AllocateMemory(pContext, sizeof(*p));
954 if (p)
955 {
956 BOOLEAN b1 = FALSE, b2 = FALSE;
957 NdisZeroMemory(p, sizeof(*p));
958 p->HeaderInfo.size = size1;
959 p->DataInfo.size = size2;
960 p->HeaderInfo.IsCached = p->DataInfo.IsCached = 1;
961 p->HeaderInfo.IsTX = p->DataInfo.IsTX = bForTx;
962 p->nofUsedBuffers = 0;
963 b1 = ParaNdis_InitialAllocatePhysicalMemory(pContext, &p->HeaderInfo);
964 if (b1) b2 = ParaNdis_InitialAllocatePhysicalMemory(pContext, &p->DataInfo);
965 if (b1 && b2)
966 {
967 BOOLEAN b = bForTx || ParaNdis_BindBufferToPacket(pContext, p);
968 if (!b)
969 {
970 DPrintf(0, ("[INITPHYS](%s) Failed to bind memory to net packet", bForTx ? "TX" : "RX"));
972 p = NULL;
973 }
974 }
975 else
976 {
977 if (b1) ParaNdis_FreePhysicalMemory(pContext, &p->HeaderInfo);
978 if (b2) ParaNdis_FreePhysicalMemory(pContext, &p->DataInfo);
979 NdisFreeMemory(p, 0, 0);
980 p = NULL;
981 DPrintf(0, ("[INITPHYS](%s) Failed to allocate memory block", bForTx ? "TX" : "RX"));
982 }
983 }
984 if (p)
985 {
986 DPrintf(3, ("[INITPHYS](%s) Header v%p(p%08lX), Data v%p(p%08lX)", bForTx ? "TX" : "RX",
987 p->HeaderInfo.Virtual, p->HeaderInfo.Physical.LowPart,
988 p->DataInfo.Virtual, p->DataInfo.Physical.LowPart));
989 }
990 return p;
991}
992
993/**********************************************************
994Allocates TX buffers according to startup setting (pContext->maxFreeTxDescriptors as got from registry)
995Buffers are chained in NetFreeSendBuffers
996Parameters:
997 context
998***********************************************************/
1000{
1001 UINT nBuffers, nMaxBuffers;
1002 DEBUG_ENTRY(4);
1003 nMaxBuffers = virtio_get_queue_size(pContext->NetSendQueue) / 2;
1004 if (nMaxBuffers > pContext->maxFreeTxDescriptors) nMaxBuffers = pContext->maxFreeTxDescriptors;
1005
1006 for (nBuffers = 0; nBuffers < nMaxBuffers; ++nBuffers)
1007 {
1008 pIONetDescriptor pBuffersDescriptor =
1010 pContext,
1011 pContext->nVirtioHeaderSize,
1013 TRUE);
1014 if (!pBuffersDescriptor) break;
1015
1016 NdisZeroMemory(pBuffersDescriptor->HeaderInfo.Virtual, pBuffersDescriptor->HeaderInfo.size);
1017 InsertTailList(&pContext->NetFreeSendBuffers, &pBuffersDescriptor->listEntry);
1018 pContext->nofFreeTxDescriptors++;
1019 }
1020
1021 pContext->maxFreeTxDescriptors = pContext->nofFreeTxDescriptors;
1022 pContext->nofFreeHardwareBuffers = pContext->nofFreeTxDescriptors * 2;
1024 DPrintf(0, ("[%s] available %d Tx descriptors, %d hw buffers",
1026}
1027
1029{
1030 UINT nBuffersToSubmit = 2;
1031 struct VirtIOBufferDescriptor sg[2];
1032 if (!pContext->bUseMergedBuffers)
1033 {
1034 sg[0].physAddr = pBufferDescriptor->HeaderInfo.Physical;
1035 sg[0].length = pBufferDescriptor->HeaderInfo.size;
1036 sg[1].physAddr = pBufferDescriptor->DataInfo.Physical;
1037 sg[1].length = pBufferDescriptor->DataInfo.size;
1038 }
1039 else
1040 {
1041 sg[0].physAddr = pBufferDescriptor->DataInfo.Physical;
1042 sg[0].length = pBufferDescriptor->DataInfo.size;
1043 nBuffersToSubmit = 1;
1044 }
1045 return 0 <= virtqueue_add_buf(
1046 pContext->NetReceiveQueue,
1047 sg,
1048 0,
1049 nBuffersToSubmit,
1050 pBufferDescriptor,
1051 NULL,
1052 0);
1053}
1054
1055
1056/**********************************************************
1057Allocates maximum RX buffers for incoming packets
1058Buffers are chained in NetReceiveBuffers
1059Parameters:
1060 context
1061***********************************************************/
1063{
1064 int nRet = 0;
1065 UINT i;
1066 DEBUG_ENTRY(4);
1067
1068 for (i = 0; i < pContext->NetMaxReceiveBuffers; ++i)
1069 {
1070 ULONG size1 = pContext->bUseMergedBuffers ? 4 : pContext->nVirtioHeaderSize;
1071 ULONG size2 = pContext->MaxPacketSize.nMaxFullSizeHwRx +
1072 (pContext->bUseMergedBuffers ? pContext->nVirtioHeaderSize : 0);
1073 pIONetDescriptor pBuffersDescriptor =
1074 AllocatePairOfBuffersOnInit(pContext, size1, size2, FALSE);
1075 if (!pBuffersDescriptor) break;
1076
1077 if (!AddRxBufferToQueue(pContext, pBuffersDescriptor))
1078 {
1079 VirtIONetFreeBufferDescriptor(pContext, pBuffersDescriptor);
1080 break;
1081 }
1082
1083 InsertTailList(&pContext->NetReceiveBuffers, &pBuffersDescriptor->listEntry);
1084
1085 pContext->NetNofReceiveBuffers++;
1086 }
1087
1088 pContext->NetMaxReceiveBuffers = pContext->NetNofReceiveBuffers;
1089 DPrintf(0, ("[%s] MaxReceiveBuffers %d\n", __FUNCTION__, pContext->NetMaxReceiveBuffers) );
1090
1092
1093 return nRet;
1094}
1095
1097{
1098 struct virtqueue *queues[3];
1099 unsigned nvqs = pContext->bHasControlQueue ? 3 : 2;
1101
1102 // We work with two or three virtqueues, 0 - receive, 1 - send, 2 - control
1104 &pContext->IODevice,
1105 nvqs,
1106 queues);
1107 if (!NT_SUCCESS(status)) {
1108 DPrintf(0, ("[%s] virtio_find_queues failed with %x\n", __FUNCTION__, status));
1110 }
1111
1112 pContext->NetReceiveQueue = queues[0];
1113 pContext->NetSendQueue = queues[1];
1114 if (pContext->bHasControlQueue) {
1115 pContext->NetControlQueue = queues[2];
1116 }
1117
1118 return NDIS_STATUS_SUCCESS;
1119}
1120
1121// called on PASSIVE upon unsuccessful Init or upon Halt
1122static void DeleteNetQueues(PARANDIS_ADAPTER *pContext)
1123{
1124 virtio_delete_queues(&pContext->IODevice);
1125}
1126
1127/**********************************************************
1128Initializes VirtIO buffering and related stuff:
1129Allocates RX and TX queues and buffers
1130Parameters:
1131 context
1132Return value:
1133 TRUE if both queues are allocated
1134***********************************************************/
1136{
1138 DEBUG_ENTRY(0);
1139
1140 pContext->ControlData.IsCached = 1;
1141 pContext->ControlData.size = 512;
1142
1143 status = FindNetQueues(pContext);
1144 if (status != NDIS_STATUS_SUCCESS) {
1145 return status;
1146 }
1147
1148 if (pContext->NetReceiveQueue && pContext->NetSendQueue)
1149 {
1150 PrepareTransmitBuffers(pContext);
1151 PrepareReceiveBuffers(pContext);
1152
1153 if (pContext->NetControlQueue)
1155 if (!pContext->NetControlQueue || !pContext->ControlData.Virtual)
1156 {
1157 DPrintf(0, ("[%s] The Control vQueue does not work!\n", __FUNCTION__) );
1158 pContext->bHasHardwareFilters = FALSE;
1159 }
1160 if (pContext->nofFreeTxDescriptors &&
1161 pContext->NetMaxReceiveBuffers &&
1162 pContext->maxFreeHardwareBuffers)
1163 {
1164 pContext->sgTxGatherTable = ParaNdis_AllocateMemory(pContext,
1165 pContext->maxFreeHardwareBuffers * sizeof(pContext->sgTxGatherTable[0]));
1166 if (!pContext->sgTxGatherTable)
1167 {
1168 DisableBothLSOPermanently(pContext, __FUNCTION__, "Can not allocate SG table");
1169 }
1171 }
1172 }
1173 else
1174 {
1175 DeleteNetQueues(pContext);
1177 }
1178 return status;
1179}
1180
1182{
1184 vdev,
1186}
1187
1188/**********************************************************
1189Finishes initialization of context structure, calling also version dependent part
1190If this procedure failed, ParaNdis_CleanupContext must be called
1191Parameters:
1192 context
1193Return value:
1194 SUCCESS or some kind of failure
1195***********************************************************/
1197{
1199 DEBUG_ENTRY(0);
1200
1201 NdisAllocateSpinLock(&pContext->SendLock);
1202#if !defined(UNIFY_LOCKS)
1204#endif
1205
1210
1212
1214 {
1215 status = ParaNdis_VirtIONetInit(pContext);
1216 }
1217
1218 pContext->Limits.nReusedRxBuffers = pContext->NetMaxReceiveBuffers / 4 + 1;
1219
1221 {
1222 JustForCheckClearInterrupt(pContext, "start 3");
1225 virtio_device_ready(&pContext->IODevice);
1226 JustForCheckClearInterrupt(pContext, "start 4");
1228 }
1229 else
1230 {
1232 }
1234 return status;
1235}
1236
1237/**********************************************************
1238Releases VirtIO related resources - queues and buffers
1239Parameters:
1240 context
1241Return value:
1242***********************************************************/
1244{
1245 BOOLEAN b;
1246 DEBUG_ENTRY(0);
1247
1248 /* list NetReceiveBuffersWaiting must be free */
1249 do
1250 {
1251 NdisAcquireSpinLock(&pContext->ReceiveLock);
1252 b = !IsListEmpty(&pContext->NetReceiveBuffersWaiting);
1253 NdisReleaseSpinLock(&pContext->ReceiveLock);
1254 if (b)
1255 {
1256 DPrintf(0, ("[%s] There are waiting buffers", __FUNCTION__));
1257 PrintStatistics(pContext);
1258 NdisMSleep(5000000);
1259 }
1260 }while (b);
1261
1262 DeleteNetQueues(pContext);
1263 virtio_device_shutdown(&pContext->IODevice);
1264 pContext->bIODeviceInitialized = FALSE;
1265
1266 /* intentionally commented out
1267 FreeDescriptorsFromList(
1268 pContext,
1269 &pContext->NetReceiveBuffersWaiting,
1270 &pContext->ReceiveLock);
1271 */
1272
1273 /* this can be freed, queue shut down */
1275 pContext,
1276 &pContext->NetReceiveBuffers,
1277 &pContext->ReceiveLock);
1278
1279 /* this can be freed, queue shut down */
1281 pContext,
1282 &pContext->NetSendBuffersInUse,
1283 &pContext->SendLock);
1284
1285 /* this can be freed, send disabled */
1287 pContext,
1288 &pContext->NetFreeSendBuffers,
1289 &pContext->SendLock);
1290
1291 if (pContext->ControlData.Virtual)
1292 ParaNdis_FreePhysicalMemory(pContext, &pContext->ControlData);
1293
1294 PrintStatistics(pContext);
1295 if (pContext->sgTxGatherTable)
1296 {
1297 NdisFreeMemory(pContext->sgTxGatherTable, 0, 0);
1298 }
1299}
1300
1302{
1303 LONG inside;;
1305 do
1306 {
1307 inside = InterlockedIncrement(&pContext->counterDPCInside);
1309 if (inside > 1)
1310 {
1311 DPrintf(0, ("[%s] waiting!", __FUNCTION__));
1312 NdisMSleep(20000);
1313 }
1314 } while (inside > 1);
1315}
1316
1317/**********************************************************
1318Frees all the resources allocated when the context initialized,
1319 calling also version-dependent part
1320Parameters:
1321 context
1322***********************************************************/
1324{
1325 UINT i;
1326
1327 /* disable any interrupt generation */
1328 if (pContext->IODevice.addr)
1329 {
1330 //int nActive;
1331 //nActive = virtio_read_isr_status(&pContext->IODevice);
1332 /* back compat - remove the OK flag only in legacy mode */
1334 JustForCheckClearInterrupt(pContext, "exit 1");
1335 //nActive += virtio_read_isr_status(&pContext->IODevice);
1336 //nActive += virtio_read_isr_status(&pContext->IODevice);
1337 //DPrintf(0, ("cleanup %d", nActive));
1338 }
1339
1340 PreventDPCServicing(pContext);
1341
1342 /****************************************
1343 ensure all the incoming packets returned,
1344 free all the buffers and their descriptors
1345 *****************************************/
1346
1347 if (pContext->bIODeviceInitialized)
1348 {
1349 JustForCheckClearInterrupt(pContext, "exit 2");
1351 JustForCheckClearInterrupt(pContext, "exit 3");
1352 }
1353
1355 VirtIONetRelease(pContext);
1356
1357 ParaNdis_FinalizeCleanup(pContext);
1358
1359 if (pContext->SendLock.SpinLock)
1360 {
1361 NdisFreeSpinLock(&pContext->SendLock);
1362 }
1363
1364#if !defined(UNIFY_LOCKS)
1365 if (pContext->ReceiveLock.SpinLock)
1366 {
1367 NdisFreeSpinLock(&pContext->ReceiveLock);
1368 }
1369#endif
1370
1371 /* free queue shared memory */
1372 for (i = 0; i < MAX_NUM_OF_QUEUES; i++) {
1373 if (pContext->SharedMemoryRanges[i].pBase != NULL) {
1375 pContext->MiniportHandle,
1376 pContext->SharedMemoryRanges[i].uLength,
1377 TRUE /* Cached */,
1378 pContext->SharedMemoryRanges[i].pBase,
1379 pContext->SharedMemoryRanges[i].BasePA);
1380 pContext->SharedMemoryRanges[i].pBase = NULL;
1381 }
1382 }
1383
1384 /* unmap our port and memory IO resources */
1385 for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
1386 {
1387 tBusResource *pRes = &pContext->AdapterResources.PciBars[i];
1388 if (pRes->pBase != NULL)
1389 {
1390 if (pRes->bPortSpace)
1391 {
1393 pContext->MiniportHandle,
1394 pRes->BasePA.LowPart,
1395 pRes->uLength,
1396 pRes->pBase);
1397 }
1398 else
1399 {
1401 pContext->MiniportHandle,
1402 pRes->pBase,
1403 pRes->uLength);
1404 }
1405 }
1406 }
1407}
1408
1409
1410/**********************************************************
1411System shutdown handler (shutdown, restart, bugcheck)
1412Parameters:
1413 context
1414***********************************************************/
1416{
1417 DEBUG_ENTRY(0); // this is only for kdbg :)
1419}
1420
1421/**********************************************************
1422Handles hardware interrupt
1423Parameters:
1424 context
1425 ULONG knownInterruptSources - bitmask of
1426Return value:
1427 TRUE, if it is our interrupt
1428 sets *pRunDpc to TRUE if the DPC should be fired
1429***********************************************************/
1431 PARANDIS_ADAPTER *pContext,
1432 OUT BOOLEAN *pRunDpc)
1433{
1435
1436 if((status == 0) ||
1438 (pContext->powerState != NdisDeviceStateD0))
1439 {
1440 *pRunDpc = FALSE;
1441 return FALSE;
1442 }
1443
1447 *pRunDpc = TRUE;
1448 return TRUE;
1449}
1450
1452 PARANDIS_ADAPTER *pContext,
1453 OUT BOOLEAN *pRunDpc,
1454 ULONG knownInterruptSources)
1455{
1456 struct virtqueue* _vq = ParaNdis_GetQueueForInterrupt(pContext, knownInterruptSources);
1457
1458 /* If interrupts for this queue disabled do nothing */
1459 if((_vq != NULL) && !ParaNDIS_IsQueueInterruptEnabled(_vq))
1460 {
1461 *pRunDpc = FALSE;
1462 }
1463 else
1464 {
1466 InterlockedOr(&pContext->InterruptStatus, (LONG)knownInterruptSources);
1467 ParaNdis_VirtIODisableIrqSynchronized(pContext, knownInterruptSources);
1468 *pRunDpc = TRUE;
1469 }
1470
1471 return *pRunDpc;
1472}
1473
1474
1475/**********************************************************
1476It is called from Rx processing routines in regular mode of operation.
1477Returns received buffer back to VirtIO queue, inserting it to NetReceiveBuffers.
1478If needed, signals end of RX pause operation
1479
1480Must be called with &pContext->ReceiveLock acquired
1481
1482Parameters:
1483 context
1484 void *pDescriptor - pIONetDescriptor to return
1485***********************************************************/
1487{
1488 DEBUG_ENTRY(4);
1489
1490 if(!pBuffersDescriptor)
1491 return;
1492
1493 RemoveEntryList(&pBuffersDescriptor->listEntry);
1494
1495 if(AddRxBufferToQueue(pContext, pBuffersDescriptor))
1496 {
1497 InsertTailList(&pContext->NetReceiveBuffers, &pBuffersDescriptor->listEntry);
1498
1499 pContext->NetNofReceiveBuffers++;
1500
1501 if (pContext->NetNofReceiveBuffers > pContext->NetMaxReceiveBuffers)
1502 {
1503 DPrintf(0, (" Error: NetNofReceiveBuffers > NetMaxReceiveBuffers(%d>%d)",
1504 pContext->NetNofReceiveBuffers, pContext->NetMaxReceiveBuffers));
1505 }
1506
1507 if (++pContext->Counters.nReusedRxBuffers >= pContext->Limits.nReusedRxBuffers)
1508 {
1509 pContext->Counters.nReusedRxBuffers = 0;
1511 }
1512
1513 if (IsListEmpty(&pContext->NetReceiveBuffersWaiting))
1514 {
1515 if (pContext->ReceiveState == srsPausing || pContext->ReceivePauseCompletionProc)
1516 {
1518 pContext->ReceiveState = srsDisabled;
1519 pContext->ReceivePauseCompletionProc = NULL;
1521 if (callback) callback(pContext);
1522 }
1523 }
1524 }
1525 else
1526 {
1527 DPrintf(0, ("FAILED TO REUSE THE BUFFER!!!!"));
1528 VirtIONetFreeBufferDescriptor(pContext, pBuffersDescriptor);
1529 pContext->NetMaxReceiveBuffers--;
1530 }
1531}
1532
1533/**********************************************************
1534It is called from Rx processing routines between power off and power on in non-paused mode (Win8).
1535Returns received buffer to NetReceiveBuffers.
1536All the buffers will be placed into Virtio queue during power-on procedure
1537
1538Must be called with &pContext->ReceiveLock acquired
1539
1540Parameters:
1541 context
1542 void *pDescriptor - pIONetDescriptor to return
1543***********************************************************/
1544static void ReuseReceiveBufferPowerOff(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor)
1545{
1546 RemoveEntryList(&pBuffersDescriptor->listEntry);
1547 InsertTailList(&pContext->NetReceiveBuffers, &pBuffersDescriptor->listEntry);
1548}
1549
1550/**********************************************************
1551It is called from Tx processing routines
1552Gets all the finished buffer from VirtIO TX path and
1553returns them to NetFreeSendBuffers
1554
1555Must be called with &pContext->SendLock acquired
1556
1557Parameters:
1558 context
1559Return value:
1560 (for reference) number of TX buffers returned
1561***********************************************************/
1563 PARANDIS_ADAPTER *pContext)
1564{
1565 UINT len, i = 0;
1566 pIONetDescriptor pBufferDescriptor;
1567
1568 DEBUG_ENTRY(4);
1569
1570 while(NULL != (pBufferDescriptor = virtqueue_get_buf(pContext->NetSendQueue, &len)))
1571 {
1572 RemoveEntryList(&pBufferDescriptor->listEntry);
1573 pContext->nofFreeTxDescriptors++;
1574 if (!pBufferDescriptor->nofUsedBuffers)
1575 {
1576 DPrintf(0, ("[%s] ERROR: nofUsedBuffers not set!", __FUNCTION__));
1577 }
1578 pContext->nofFreeHardwareBuffers += pBufferDescriptor->nofUsedBuffers;
1579 ParaNdis_OnTransmitBufferReleased(pContext, pBufferDescriptor);
1580 InsertTailList(&pContext->NetFreeSendBuffers, &pBufferDescriptor->listEntry);
1581 DPrintf(3, ("[%s] Free Tx: desc %d, buff %d", __FUNCTION__, pContext->nofFreeTxDescriptors, pContext->nofFreeHardwareBuffers));
1582 pBufferDescriptor->nofUsedBuffers = 0;
1583 ++i;
1584 }
1585 if (i)
1586 {
1588 pContext->bDoKickOnNoBuffer = TRUE;
1589 pContext->nDetectedStoppedTx = 0;
1590 }
1591 DEBUG_EXIT_STATUS((i ? 3 : 5), i);
1592 return i;
1593}
1594
1595static ULONG FORCEINLINE QueryTcpHeaderOffset(PVOID packetData, ULONG ipHeaderOffset, ULONG ipPacketLength)
1596{
1597 ULONG res;
1599 (PUCHAR)packetData + ipHeaderOffset,
1600 ipPacketLength,
1601 __FUNCTION__);
1602 if (ppr.xxpStatus == ppresXxpKnown)
1603 {
1604 res = ipHeaderOffset + ppr.ipHeaderSize;
1605 }
1606 else
1607 {
1608 DPrintf(0, ("[%s] ERROR: NOT a TCP or UDP packet - expected troubles!", __FUNCTION__));
1609 res = 0;
1610 }
1611 return res;
1612}
1613
1614
1615/*********************************************************
1616Called with from ProcessTx routine with TxLock held
1617Uses pContext->sgTxGatherTable
1618***********************************************************/
1620{
1622 tMapperResult mapResult = {0,0,0};
1623 // populating priority tag or LSO MAY require additional SG element
1624 UINT nRequiredBuffers;
1625 BOOLEAN bUseCopy = FALSE;
1626 struct VirtIOBufferDescriptor *sg = pContext->sgTxGatherTable;
1627
1628 nRequiredBuffers = Params->nofSGFragments + 1 + ((Params->flags & (pcrPriorityTag | pcrLSO)) ? 1 : 0);
1629
1630 result.size = 0;
1631 result.error = cpeOK;
1632 if (!pContext->bUseScatterGather || // only copy available
1633 Params->nofSGFragments == 0 || // theoretical case
1634 !sg || // only copy available
1635 ((~Params->flags & pcrLSO) && nRequiredBuffers > pContext->maxFreeHardwareBuffers) // to many fragments and normal size of packet
1636 )
1637 {
1638 nRequiredBuffers = 2;
1639 bUseCopy = TRUE;
1640 }
1641 else if (pContext->bUseIndirect && !(Params->flags & pcrNoIndirect))
1642 {
1643 nRequiredBuffers = 1;
1644 }
1645
1646 // I do not think this will help, but at least we can try freeing some buffers right now
1647 if (pContext->nofFreeHardwareBuffers < nRequiredBuffers || !pContext->nofFreeTxDescriptors)
1648 {
1650 }
1651
1652 if (nRequiredBuffers > pContext->maxFreeHardwareBuffers)
1653 {
1654 // LSO and too many buffers, impossible to send
1655 result.error = cpeTooLarge;
1656 DPrintf(0, ("[%s] ERROR: too many fragments(%d required, %d max.avail)!", __FUNCTION__,
1657 nRequiredBuffers, pContext->maxFreeHardwareBuffers));
1658 }
1659 else if (pContext->nofFreeHardwareBuffers < nRequiredBuffers || !pContext->nofFreeTxDescriptors)
1660 {
1662 result.error = cpeNoBuffer;
1663 }
1664 else if (Params->offloadMss && bUseCopy)
1665 {
1666 result.error = cpeInternalError;
1667 DPrintf(0, ("[%s] ERROR: expecting SG for TSO! (%d buffers, %d bytes)", __FUNCTION__,
1668 Params->nofSGFragments, Params->ulDataSize));
1669 }
1670 else if (bUseCopy)
1671 {
1673 }
1674 else
1675 {
1676 UINT nMappedBuffers;
1677 ULONGLONG paOfIndirectArea = 0;
1678 PVOID vaOfIndirectArea = NULL;
1679 pIONetDescriptor pBuffersDescriptor = (pIONetDescriptor)RemoveHeadList(&pContext->NetFreeSendBuffers);
1680 pContext->nofFreeTxDescriptors--;
1681 NdisZeroMemory(pBuffersDescriptor->HeaderInfo.Virtual, pBuffersDescriptor->HeaderInfo.size);
1682 sg[0].physAddr = pBuffersDescriptor->HeaderInfo.Physical;
1683 sg[0].length = pBuffersDescriptor->HeaderInfo.size;
1685 pContext,
1686 Params->packet,
1687 Params->ReferenceValue,
1688 sg + 1,
1689 pBuffersDescriptor,
1690 &mapResult);
1691 nMappedBuffers = mapResult.usBuffersMapped;
1692 if (nMappedBuffers)
1693 {
1694 nMappedBuffers++;
1695 if (pContext->bUseIndirect && !(Params->flags & pcrNoIndirect))
1696 {
1697 ULONG space1 = (mapResult.usBufferSpaceUsed + 7) & ~7;
1698 ULONG space2 = nMappedBuffers * SIZE_OF_SINGLE_INDIRECT_DESC;
1699 if (pBuffersDescriptor->DataInfo.size >= (space1 + space2))
1700 {
1701 vaOfIndirectArea = RtlOffsetToPointer(pBuffersDescriptor->DataInfo.Virtual, space1);
1702 paOfIndirectArea = pBuffersDescriptor->DataInfo.Physical.QuadPart + space1;
1703 pContext->extraStatistics.framesIndirect++;
1704 }
1705 else if (nMappedBuffers <= pContext->nofFreeHardwareBuffers)
1706 {
1707 // send as is, no indirect
1708 }
1709 else
1710 {
1711 result.error = cpeNoIndirect;
1712 DPrintf(0, ("[%s] Unexpected ERROR of placement!", __FUNCTION__));
1713 }
1714 }
1715 if (result.error == cpeOK)
1716 {
1717 if (Params->flags & (pcrTcpChecksum | pcrUdpChecksum))
1718 {
1719 unsigned short addPriorityLen = (Params->flags & pcrPriorityTag) ? ETH_PRIORITY_HEADER_SIZE : 0;
1720 if (pContext->bDoHardwareChecksum)
1721 {
1722 virtio_net_hdr_basic *pheader = pBuffersDescriptor->HeaderInfo.Virtual;
1724 if (!Params->tcpHeaderOffset)
1725 {
1726 Params->tcpHeaderOffset = QueryTcpHeaderOffset(
1727 pBuffersDescriptor->DataInfo.Virtual,
1728 pContext->Offload.ipHeaderOffset + addPriorityLen,
1729 mapResult.usBufferSpaceUsed - pContext->Offload.ipHeaderOffset - addPriorityLen);
1730 }
1731 else
1732 {
1733 Params->tcpHeaderOffset += addPriorityLen;
1734 }
1735 pheader->csum_start = (USHORT)Params->tcpHeaderOffset;
1737 }
1738 else
1739 {
1740 // emulation mode - it is slow and intended only for test of flows
1741 // and debugging of WLK test cases
1742 PVOID pCopy = ParaNdis_AllocateMemory(pContext, Params->ulDataSize);
1743 if (pCopy)
1744 {
1746 // duplicate entire packet
1747 ParaNdis_PacketCopier(Params->packet, pCopy, Params->ulDataSize, Params->ReferenceValue, FALSE);
1748 // calculate complete TCP/UDP checksum
1750 RtlOffsetToPointer(pCopy, pContext->Offload.ipHeaderOffset + addPriorityLen),
1751 Params->ulDataSize - pContext->Offload.ipHeaderOffset - addPriorityLen,
1753 __FUNCTION__);
1754 // data portion in aside buffer contains complete IP+TCP header
1755 // rewrite copy of original buffer by one new with calculated data
1757 pBuffersDescriptor->DataInfo.Virtual,
1758 pCopy,
1759 mapResult.usBufferSpaceUsed);
1760 NdisFreeMemory(pCopy, 0, 0);
1761 }
1762 }
1763 }
1764
1765 if (0 <= virtqueue_add_buf(
1766 pContext->NetSendQueue,
1767 sg,
1768 nMappedBuffers,
1769 0,
1770 pBuffersDescriptor,
1771 vaOfIndirectArea,
1772 paOfIndirectArea))
1773 {
1774 pBuffersDescriptor->nofUsedBuffers = nMappedBuffers;
1775 pContext->nofFreeHardwareBuffers -= nMappedBuffers;
1776 if (pContext->minFreeHardwareBuffers > pContext->nofFreeHardwareBuffers)
1777 pContext->minFreeHardwareBuffers = pContext->nofFreeHardwareBuffers;
1778 pBuffersDescriptor->ReferenceValue = Params->ReferenceValue;
1779 result.size = Params->ulDataSize;
1780 DPrintf(2, ("[%s] Submitted %d buffers (%d bytes), avail %d desc, %d bufs",
1781 __FUNCTION__, nMappedBuffers, result.size,
1782 pContext->nofFreeTxDescriptors, pContext->nofFreeHardwareBuffers
1783 ));
1784 }
1785 else
1786 {
1787 result.error = cpeInternalError;
1788 DPrintf(0, ("[%s] Unexpected ERROR adding buffer to TX engine!..", __FUNCTION__));
1789 }
1790 }
1791 }
1792 else
1793 {
1794 DPrintf(0, ("[%s] Unexpected ERROR: packet not mapped!", __FUNCTION__));
1795 result.error = cpeInternalError;
1796 }
1797
1798 if (result.error == cpeOK)
1799 {
1800 UCHAR ethernetHeader[sizeof(ETH_HEADER)];
1801 eInspectedPacketType packetType;
1802 /* get the ethernet header for review */
1803 ParaNdis_PacketCopier(Params->packet, ethernetHeader, sizeof(ethernetHeader), Params->ReferenceValue, TRUE);
1804 packetType = QueryPacketType(ethernetHeader);
1805 DebugDumpPacket("sending", ethernetHeader, 3);
1806 InsertTailList(&pContext->NetSendBuffersInUse, &pBuffersDescriptor->listEntry);
1807 pContext->Statistics.ifHCOutOctets += result.size;
1808 switch (packetType)
1809 {
1810 case iptBroadcast:
1811 pContext->Statistics.ifHCOutBroadcastOctets += result.size;
1812 pContext->Statistics.ifHCOutBroadcastPkts++;
1813 break;
1814 case iptMulticast:
1815 pContext->Statistics.ifHCOutMulticastOctets += result.size;
1816 pContext->Statistics.ifHCOutMulticastPkts++;
1817 break;
1818 default:
1819 pContext->Statistics.ifHCOutUcastOctets += result.size;
1820 pContext->Statistics.ifHCOutUcastPkts++;
1821 break;
1822 }
1823
1824 if (Params->flags & pcrLSO)
1825 pContext->extraStatistics.framesLSO++;
1826 }
1827 else
1828 {
1829 pContext->nofFreeTxDescriptors++;
1830 InsertHeadList(&pContext->NetFreeSendBuffers, &pBuffersDescriptor->listEntry);
1831 }
1832 }
1833 if (result.error == cpeNoBuffer && pContext->bDoKickOnNoBuffer)
1834 {
1836 pContext->bDoKickOnNoBuffer = FALSE;
1837 }
1838 if (result.error == cpeOK)
1839 {
1840 if (Params->flags & (pcrTcpChecksum | pcrUdpChecksum))
1841 pContext->extraStatistics.framesCSOffload++;
1842 }
1843 return result;
1844}
1845
1846
1847/**********************************************************
1848It is called from Tx processing routines
1849Prepares the VirtIO buffer and copies to it the data from provided packet
1850
1851Must be called with &pContext->SendLock acquired
1852
1853Parameters:
1854 context
1855 tPacketType packet specific type is NDIS dependent
1856 tCopyPacketDataFunction PacketCopier procedure for NDIS-specific type of packet
1857Return value:
1858 (for reference) number of TX buffers returned
1859***********************************************************/
1861 PARANDIS_ADAPTER *pContext,
1862 tTxOperationParameters *pParams)
1863{
1865 tCopyPacketResult CopierResult;
1866 struct VirtIOBufferDescriptor sg[2];
1867 pIONetDescriptor pBuffersDescriptor = NULL;
1868 ULONG flags = pParams->flags;
1869 UINT nRequiredHardwareBuffers = 2;
1870 result.size = 0;
1871 result.error = cpeOK;
1872 if (pContext->nofFreeHardwareBuffers < nRequiredHardwareBuffers ||
1873 IsListEmpty(&pContext->NetFreeSendBuffers))
1874 {
1875 result.error = cpeNoBuffer;
1876 }
1877 if(result.error == cpeOK)
1878 {
1879 pBuffersDescriptor = (pIONetDescriptor)RemoveHeadList(&pContext->NetFreeSendBuffers);
1880 NdisZeroMemory(pBuffersDescriptor->HeaderInfo.Virtual, pBuffersDescriptor->HeaderInfo.size);
1881 sg[0].physAddr = pBuffersDescriptor->HeaderInfo.Physical;
1882 sg[0].length = pBuffersDescriptor->HeaderInfo.size;
1883 sg[1].physAddr = pBuffersDescriptor->DataInfo.Physical;
1884 CopierResult = ParaNdis_PacketCopier(
1885 pParams->packet,
1886 pBuffersDescriptor->DataInfo.Virtual,
1887 pBuffersDescriptor->DataInfo.size,
1888 pParams->ReferenceValue,
1889 FALSE);
1890 sg[1].length = result.size = CopierResult.size;
1891 // did NDIS ask us to compute CS?
1893 {
1894 // we asked
1895 unsigned short addPriorityLen = (pParams->flags & pcrPriorityTag) ? ETH_PRIORITY_HEADER_SIZE : 0;
1896 PVOID ipPacket = RtlOffsetToPointer(
1897 pBuffersDescriptor->DataInfo.Virtual, pContext->Offload.ipHeaderOffset + addPriorityLen);
1898 ULONG ipPacketLength = CopierResult.size - pContext->Offload.ipHeaderOffset - addPriorityLen;
1899 if (!pParams->tcpHeaderOffset &&
1901 {
1903 pBuffersDescriptor->DataInfo.Virtual,
1904 pContext->Offload.ipHeaderOffset + addPriorityLen,
1905 ipPacketLength);
1906 }
1907 else
1908 {
1909 pParams->tcpHeaderOffset += addPriorityLen;
1910 }
1911
1912 if (pContext->bDoHardwareChecksum)
1913 {
1915 {
1916 // hardware offload
1917 virtio_net_hdr_basic *pvnh = (virtio_net_hdr_basic *)pBuffersDescriptor->HeaderInfo.Virtual;
1918 pvnh->csum_start = (USHORT)pParams->tcpHeaderOffset;
1921 }
1922 if (flags & (pcrIpChecksum))
1923 {
1925 ipPacket,
1926 ipPacketLength,
1928 __FUNCTION__);
1929 }
1930 }
1931 else if (CopierResult.size > pContext->Offload.ipHeaderOffset)
1932 {
1933 ULONG csFlags = 0;
1936 // software offload
1938 ipPacket,
1939 ipPacketLength,
1940 csFlags,
1941 __FUNCTION__);
1942 }
1943 else
1944 {
1945 DPrintf(0, ("[%s] ERROR: Invalid buffer size for offload!", __FUNCTION__));
1946 result.size = 0;
1947 result.error = cpeInternalError;
1948 }
1949 }
1950 pContext->nofFreeTxDescriptors--;
1951 if (result.size)
1952 {
1953 eInspectedPacketType packetType;
1954 packetType = QueryPacketType(pBuffersDescriptor->DataInfo.Virtual);
1955 DebugDumpPacket("sending", pBuffersDescriptor->DataInfo.Virtual, 3);
1956
1957 pBuffersDescriptor->nofUsedBuffers = nRequiredHardwareBuffers;
1958 pContext->nofFreeHardwareBuffers -= nRequiredHardwareBuffers;
1959 if (pContext->minFreeHardwareBuffers > pContext->nofFreeHardwareBuffers)
1960 pContext->minFreeHardwareBuffers = pContext->nofFreeHardwareBuffers;
1961 if (0 > virtqueue_add_buf(
1962 pContext->NetSendQueue,
1963 sg,
1964 2,
1965 0,
1966 pBuffersDescriptor,
1967 NULL,
1968 0
1969 ))
1970 {
1971 pBuffersDescriptor->nofUsedBuffers = 0;
1972 pContext->nofFreeHardwareBuffers += nRequiredHardwareBuffers;
1973 result.error = cpeInternalError;
1974 result.size = 0;
1975 DPrintf(0, ("[%s] Unexpected ERROR adding buffer to TX engine!..", __FUNCTION__));
1976 }
1977 else
1978 {
1979 DPrintf(2, ("[%s] Submitted %d buffers (%d bytes), avail %d desc, %d bufs",
1980 __FUNCTION__, nRequiredHardwareBuffers, result.size,
1981 pContext->nofFreeTxDescriptors, pContext->nofFreeHardwareBuffers
1982 ));
1983 }
1984 if (result.error != cpeOK)
1985 {
1986 InsertTailList(&pContext->NetFreeSendBuffers, &pBuffersDescriptor->listEntry);
1987 pContext->nofFreeTxDescriptors++;
1988 }
1989 else
1990 {
1991 ULONG reportedSize = pParams->ulDataSize;
1992 pBuffersDescriptor->ReferenceValue = pParams->ReferenceValue;
1993 InsertTailList(&pContext->NetSendBuffersInUse, &pBuffersDescriptor->listEntry);
1994 pContext->Statistics.ifHCOutOctets += reportedSize;
1995 switch (packetType)
1996 {
1997 case iptBroadcast:
1998 pContext->Statistics.ifHCOutBroadcastOctets += reportedSize;
1999 pContext->Statistics.ifHCOutBroadcastPkts++;
2000 break;
2001 case iptMulticast:
2002 pContext->Statistics.ifHCOutMulticastOctets += reportedSize;
2003 pContext->Statistics.ifHCOutMulticastPkts++;
2004 break;
2005 default:
2006 pContext->Statistics.ifHCOutUcastOctets += reportedSize;
2007 pContext->Statistics.ifHCOutUcastPkts++;
2008 break;
2009 }
2010 }
2011 }
2012 else
2013 {
2014 DPrintf(0, ("[%s] Unexpected ERROR in copying packet data! Continue...", __FUNCTION__));
2015 InsertTailList(&pContext->NetFreeSendBuffers, &pBuffersDescriptor->listEntry);
2016 pContext->nofFreeTxDescriptors++;
2017 // the buffer is not copied and the callback will not be called
2018 result.error = cpeInternalError;
2019 }
2020 }
2021
2022 return result;
2023}
2024
2026{
2027 ULONG b;
2028 if (len <= sizeof(ETH_HEADER)) return FALSE;
2029 if (len > pContext->MaxPacketSize.nMaxFullSizeHwRx) return FALSE;
2030 if (len > pContext->MaxPacketSize.nMaxFullSizeOS && !ETH_HAS_PRIO_HEADER(address)) return FALSE;
2031 *pType = QueryPacketType(address);
2032 if (pContext->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) return TRUE;
2033
2034 switch(*pType)
2035 {
2036 case iptBroadcast:
2038 break;
2039 case iptMulticast:
2041 if (!b && (pContext->PacketFilter & NDIS_PACKET_TYPE_MULTICAST))
2042 {
2044 b = 1;
2045 for (i = 0; b && i < n; i += ETH_LENGTH_OF_ADDRESS)
2046 {
2048 }
2049 b = !b;
2050 }
2051 break;
2052 default:
2054 b = !b && (pContext->PacketFilter & NDIS_PACKET_TYPE_DIRECTED);
2055 break;
2056 }
2057 if (!b)
2058 {
2059 pContext->extraStatistics.framesFilteredOut++;
2060 }
2061 return b;
2062}
2063
2064void
2066{
2067 // Ethernet standard declares minimal possible packet size
2068 // Packets smaller than that must be padded before transfer
2069 // Ethernet HW pads packets on transmit, however in our case
2070 // some packets do not travel over Ethernet but being routed
2071 // guest-to-guest by virtual switch.
2072 // In this case padding is not performed and we may
2073 // receive packet smaller than minimal allowed size. This is not
2074 // a problem for real life scenarios however WHQL/HCK contains
2075 // tests that check padding of received packets.
2076 // To make these tests happy we have to pad small packets on receive
2077
2078 //NOTE: This function assumes that VLAN header has been already stripped out
2079
2080 if(*pLength < ETH_MIN_PACKET_SIZE)
2081 {
2082 RtlZeroMemory(RtlOffsetToPointer(pDataBuffer, *pLength), ETH_MIN_PACKET_SIZE - *pLength);
2083 *pLength = ETH_MIN_PACKET_SIZE;
2084 }
2085}
2086
2087/**********************************************************
2088Manages RX path, calling NDIS-specific procedure for packet indication
2089Parameters:
2090 context
2091***********************************************************/
2092static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER *pContext, ULONG ulMaxPacketsToIndicate)
2093{
2094 pIONetDescriptor pBuffersDescriptor;
2095 UINT len, headerSize = pContext->nVirtioHeaderSize;
2096 eInspectedPacketType packetType = iptInvalid;
2097 UINT nReceived = 0, nRetrieved = 0, nReported = 0;
2098 tPacketIndicationType *pBatchOfPackets;
2099 UINT maxPacketsInBatch = pContext->NetMaxReceiveBuffers;
2100 pBatchOfPackets = pContext->bBatchReceive ?
2101 ParaNdis_AllocateMemory(pContext, maxPacketsInBatch * sizeof(tPacketIndicationType)) : NULL;
2102 NdisAcquireSpinLock(&pContext->ReceiveLock);
2103 while ((nReported < ulMaxPacketsToIndicate) && NULL != (pBuffersDescriptor = virtqueue_get_buf(pContext->NetReceiveQueue, &len)))
2104 {
2105 PVOID pDataBuffer = RtlOffsetToPointer(pBuffersDescriptor->DataInfo.Virtual, pContext->bUseMergedBuffers ? pContext->nVirtioHeaderSize : 0);
2106 RemoveEntryList(&pBuffersDescriptor->listEntry);
2107 InsertTailList(&pContext->NetReceiveBuffersWaiting, &pBuffersDescriptor->listEntry);
2108 pContext->NetNofReceiveBuffers--;
2109 nRetrieved++;
2110 DPrintf(2, ("[%s] retrieved header+%d b.", __FUNCTION__, len - headerSize));
2111 DebugDumpPacket("receive", pDataBuffer, 3);
2112
2113 if( !pContext->bSurprizeRemoved &&
2114 ShallPassPacket(pContext, pDataBuffer, len - headerSize, &packetType) &&
2115 pContext->ReceiveState == srsEnabled &&
2116 pContext->bConnected)
2117 {
2118 BOOLEAN b = FALSE;
2119 ULONG length = len - headerSize;
2120 if (!pBatchOfPackets)
2121 {
2122 NdisReleaseSpinLock(&pContext->ReceiveLock);
2124 pContext,
2125 pDataBuffer,
2126 &length,
2127 FALSE,
2128 pBuffersDescriptor);
2129 NdisAcquireSpinLock(&pContext->ReceiveLock);
2130 }
2131 else
2132 {
2135 pContext,
2136 pDataBuffer,
2137 &length,
2138 TRUE,
2139 pBuffersDescriptor);
2140 b = packet != NULL;
2141 if (b) pBatchOfPackets[nReceived] = packet;
2142 }
2143 if (!b)
2144 {
2145 pContext->ReuseBufferProc(pContext, pBuffersDescriptor);
2146 //only possible reason for that is unexpected Vlan tag
2147 //shall I count it as error?
2148 pContext->Statistics.ifInErrors++;
2149 pContext->Statistics.ifInDiscards++;
2150 }
2151 else
2152 {
2153 nReceived++;
2154 nReported++;
2155 pContext->Statistics.ifHCInOctets += length;
2156 switch(packetType)
2157 {
2158 case iptBroadcast:
2159 pContext->Statistics.ifHCInBroadcastPkts++;
2161 break;
2162 case iptMulticast:
2163 pContext->Statistics.ifHCInMulticastPkts++;
2165 break;
2166 default:
2167 pContext->Statistics.ifHCInUcastPkts++;
2168 pContext->Statistics.ifHCInUcastOctets += length;
2169 break;
2170 }
2171 if (pBatchOfPackets && nReceived == maxPacketsInBatch)
2172 {
2173 DPrintf(1, ("[%s] received %d buffers of max %d", __FUNCTION__, nReceived, ulMaxPacketsToIndicate));
2174 NdisReleaseSpinLock(&pContext->ReceiveLock);
2175 ParaNdis_IndicateReceivedBatch(pContext, pBatchOfPackets, nReceived);
2176 NdisAcquireSpinLock(&pContext->ReceiveLock);
2177 nReceived = 0;
2178 }
2179 }
2180 }
2181 else
2182 {
2183 // reuse packet, there is no data or the RX is suppressed
2184 pContext->ReuseBufferProc(pContext, pBuffersDescriptor);
2185 }
2186 }
2187 ParaNdis_DebugHistory(pContext, hopReceiveStat, NULL, nRetrieved, nReported, pContext->NetNofReceiveBuffers);
2188 NdisReleaseSpinLock(&pContext->ReceiveLock);
2189 if (nReceived && pBatchOfPackets)
2190 {
2191 DPrintf(1, ("[%s]%d: received %d buffers of max %d", __FUNCTION__, KeGetCurrentProcessorNumber(), nReceived, ulMaxPacketsToIndicate));
2192 ParaNdis_IndicateReceivedBatch(pContext, pBatchOfPackets, nReceived);
2193 }
2194 if (pBatchOfPackets) NdisFreeMemory(pBatchOfPackets, 0, 0);
2195 return nReported;
2196}
2197
2199{
2201 if (pContext->bLinkDetectSupported)
2202 {
2203 USHORT linkStatus = 0;
2204 USHORT offset = sizeof(pContext->CurrentMacAddress);
2205 // link changed
2206 virtio_get_config(&pContext->IODevice, offset, &linkStatus, sizeof(linkStatus));
2207 bConnected = (linkStatus & VIRTIO_NET_S_LINK_UP) != 0;
2208 }
2209 ParaNdis_IndicateConnect(pContext, bConnected, bForce);
2210}
2211
2213{
2214 struct virtqueue * _vq = (struct virtqueue *) SyncContext->Parameter;
2215 bool res = true;
2216 if (!virtqueue_enable_cb(_vq))
2217 {
2219 res = false;
2220 }
2221
2222 ParaNdis_DebugHistory(SyncContext->pContext, hopDPC, (PVOID)SyncContext->Parameter, 0x20, res, 0);
2223 return !res;
2224}
2225/**********************************************************
2226DPC implementation, common for both NDIS
2227Parameters:
2228 context
2229***********************************************************/
2230ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext, ULONG ulMaxPacketsToIndicate)
2231{
2232 ULONG stillRequiresProcessing = 0;
2233 ULONG interruptSources;
2234 UINT uIndicatedRXPackets = 0;
2235 UINT numOfPacketsToIndicate = min(ulMaxPacketsToIndicate, pContext->uNumberOfHandledRXPacketsInDPC);
2236
2237 DEBUG_ENTRY(5);
2238 if (pContext->bEnableInterruptHandlingDPC)
2239 {
2241 if (pContext->bEnableInterruptHandlingDPC)
2242 {
2243 BOOLEAN bDoKick = FALSE;
2244
2245 InterlockedExchange(&pContext->bDPCInactive, 0);
2246 interruptSources = InterlockedExchange(&pContext->InterruptStatus, 0);
2247 ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)1, interruptSources, 0, 0);
2248 if ((interruptSources & isControl) && pContext->bLinkDetectSupported)
2249 {
2251 }
2252 if (interruptSources & isTransmit)
2253 {
2254 bDoKick = ParaNdis_ProcessTx(pContext, TRUE, TRUE);
2255 }
2256 if (interruptSources & isReceive)
2257 {
2258 int nRestartResult = 0;
2259
2260 do
2261 {
2262 LONG rxActive = InterlockedIncrement(&pContext->dpcReceiveActive);
2263 if (rxActive == 1)
2264 {
2265 uIndicatedRXPackets += ParaNdis_ProcessRxPath(pContext, numOfPacketsToIndicate - uIndicatedRXPackets);
2267 NdisAcquireSpinLock(&pContext->ReceiveLock);
2268 nRestartResult = ParaNdis_SynchronizeWithInterrupt(
2269 pContext, pContext->ulRxMessage, RestartQueueSynchronously, pContext->NetReceiveQueue);
2270 ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)3, nRestartResult, 0, 0);
2271 NdisReleaseSpinLock(&pContext->ReceiveLock);
2272 DPrintf(nRestartResult ? 2 : 6, ("[%s] queue restarted%s", __FUNCTION__, nRestartResult ? "(Rerun)" : "(Done)"));
2273
2274 if (uIndicatedRXPackets < numOfPacketsToIndicate)
2275 {
2276
2277 }
2278 else if (uIndicatedRXPackets == numOfPacketsToIndicate)
2279 {
2280 DPrintf(1, ("[%s] Breaking Rx loop after %d indications", __FUNCTION__, uIndicatedRXPackets));
2281 ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)4, nRestartResult, 0, 0);
2282 break;
2283 }
2284 else
2285 {
2286 DPrintf(0, ("[%s] Glitch found: %d allowed, %d indicated", __FUNCTION__, numOfPacketsToIndicate, uIndicatedRXPackets));
2287 ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)6, nRestartResult, 0, 0);
2288 }
2289 }
2290 else
2291 {
2293 if (!nRestartResult)
2294 {
2295 NdisAcquireSpinLock(&pContext->ReceiveLock);
2296 nRestartResult = ParaNdis_SynchronizeWithInterrupt(
2297 pContext, pContext->ulRxMessage, RestartQueueSynchronously, pContext->NetReceiveQueue);
2298 ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)5, nRestartResult, 0, 0);
2299 NdisReleaseSpinLock(&pContext->ReceiveLock);
2300 }
2301 DPrintf(1, ("[%s] Skip Rx processing no.%d", __FUNCTION__, rxActive));
2302 break;
2303 }
2304 } while (nRestartResult);
2305
2306 if (nRestartResult) stillRequiresProcessing |= isReceive;
2307 }
2308
2309 if (interruptSources & isTransmit)
2310 {
2311 NdisAcquireSpinLock(&pContext->SendLock);
2313 stillRequiresProcessing |= isTransmit;
2314 if(bDoKick)
2315 {
2316#ifdef PARANDIS_TEST_TX_KICK_ALWAYS
2318#else
2319 virtqueue_kick(pContext->NetSendQueue);
2320#endif
2321 }
2322 NdisReleaseSpinLock(&pContext->SendLock);
2323 }
2324 }
2326 ParaNdis_DebugHistory(pContext, hopDPC, NULL, stillRequiresProcessing, pContext->nofFreeHardwareBuffers, pContext->nofFreeTxDescriptors);
2327 }
2328 return stillRequiresProcessing;
2329}
2330
2331/**********************************************************
2332Periodically called procedure, checking dpc activity
2333If DPC are not running, it does exactly the same that the DPC
2334Parameters:
2335 context
2336***********************************************************/
2338{
2339 BOOLEAN bStopped;
2340 BOOLEAN bReportHang = FALSE;
2341 bStopped = 0 != InterlockedExchange(&pContext->bDPCInactive, TRUE);
2342
2343 if (bStopped)
2344 {
2345 pContext->nDetectedInactivity++;
2346 if (pContext->nEnableDPCChecker)
2347 {
2348 if (pContext->NetTxPacketsToReturn)
2349 {
2350 DPrintf(0, ("[%s] - NO ACTIVITY!", __FUNCTION__));
2351 if (!pContext->Limits.nPrintDiagnostic) PrintStatistics(pContext);
2352 if (pContext->nEnableDPCChecker > 1)
2353 {
2354 int isrStatus1, isrStatus2;
2355 isrStatus1 = virtio_read_isr_status(&pContext->IODevice);
2356 isrStatus2 = virtio_read_isr_status(&pContext->IODevice);
2357 if (isrStatus1 || isrStatus2)
2358 {
2359 DPrintf(0, ("WARNING: Interrupt status %d=>%d", isrStatus1, isrStatus2));
2360 }
2361 }
2362 // simulateDPC
2363 InterlockedOr(&pContext->InterruptStatus, isAny);
2365 }
2366 }
2367 }
2368 else
2369 {
2370 pContext->nDetectedInactivity = 0;
2371 }
2372
2373 NdisAcquireSpinLock(&pContext->SendLock);
2374 if (pContext->nofFreeHardwareBuffers != pContext->maxFreeHardwareBuffers)
2375 {
2376 if (pContext->nDetectedStoppedTx++ > 1)
2377 {
2378 DPrintf(0, ("[%s] - Suspicious Tx inactivity (%d)!", __FUNCTION__, pContext->nofFreeHardwareBuffers));
2379 //bReportHang = TRUE;
2380#ifdef DBG_USE_VIRTIO_PCI_ISR_FOR_HOST_REPORT
2381 WriteVirtIODeviceByte(pContext->IODevice.isr, 0);
2382#endif
2383 }
2384 }
2385 NdisReleaseSpinLock(&pContext->SendLock);
2386
2387
2388 if (pContext->Limits.nPrintDiagnostic &&
2389 ++pContext->Counters.nPrintDiagnostic >= pContext->Limits.nPrintDiagnostic)
2390 {
2391 pContext->Counters.nPrintDiagnostic = 0;
2392 // todo - collect more and put out optionally
2393 PrintStatistics(pContext);
2394 }
2395
2396 if (pContext->Statistics.ifHCInOctets == pContext->Counters.prevIn)
2397 {
2398 pContext->Counters.nRxInactivity++;
2399 if (pContext->Counters.nRxInactivity >= 10)
2400 {
2401//#define CRASH_ON_NO_RX
2402#if defined(CRASH_ON_NO_RX)
2404 proc(pContext);
2405#endif
2406 }
2407 }
2408 else
2409 {
2410 pContext->Counters.nRxInactivity = 0;
2411 pContext->Counters.prevIn = pContext->Statistics.ifHCInOctets;
2412 }
2413 return bReportHang;
2414}
2415
2416/**********************************************************
2417Common implementation of periodic poll
2418Parameters:
2419 context
2420Return:
2421 TRUE, if reset required
2422***********************************************************/
2424{
2425 static int nHangOn = 0;
2426 BOOLEAN b = nHangOn >= 3 && nHangOn < 6;
2427 DEBUG_ENTRY(3);
2428 b |= CheckRunningDpc(pContext);
2429 //uncomment to cause 3 consecutive resets
2430 //nHangOn++;
2431 DEBUG_EXIT_STATUS(b ? 0 : 6, b);
2432 return b;
2433}
2434
2435/**********************************************************
2436Common handler of multicast address configuration
2437Parameters:
2438 PVOID Buffer array of addresses from NDIS
2439 ULONG BufferSize size of incoming buffer
2440 PUINT pBytesRead update on success
2441 PUINT pBytesNeeded update on wrong buffer size
2442Return value:
2443 SUCCESS or kind of failure
2444***********************************************************/
2446 PARANDIS_ADAPTER *pContext,
2447 PVOID Buffer,
2449 PUINT pBytesRead,
2450 PUINT pBytesNeeded)
2451{
2454 if (length > sizeof(pContext->MulticastData.MulticastList))
2455 {
2457 *pBytesNeeded = sizeof(pContext->MulticastData.MulticastList);
2458 }
2459 else if (length % ETH_LENGTH_OF_ADDRESS)
2460 {
2463 }
2464 else
2465 {
2467 if (length)
2470 DPrintf(1, ("[%s] New multicast list of %d bytes", __FUNCTION__, length));
2471 *pBytesRead = length;
2473 }
2474 return status;
2475}
2476
2477/**********************************************************
2478Callable from synchronized routine or interrupt handler
2479to enable or disable Rx and/or Tx interrupt generation
2480Parameters:
2481 context
2482 interruptSource - isReceive, isTransmit
2483 b - 1/0 enable/disable
2484***********************************************************/
2486{
2487 if (interruptSource & isTransmit)
2489 if (interruptSource & isReceive)
2491 ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)0x10, interruptSource, TRUE, 0);
2492}
2493
2495{
2496 if (interruptSource & isTransmit)
2498 if (interruptSource & isReceive)
2500 ParaNdis_DebugHistory(pContext, hopDPC, (PVOID)0x10, interruptSource, FALSE, 0);
2501}
2502
2503/**********************************************************
2504Common handler of PnP events
2505Parameters:
2506Return value:
2507***********************************************************/
2509 PARANDIS_ADAPTER *pContext,
2510 NDIS_DEVICE_PNP_EVENT pEvent,
2511 PVOID pInfo,
2512 ULONG ulSize)
2513{
2514 const char *pName = "";
2515 DEBUG_ENTRY(0);
2516#undef MAKECASE
2517#define MAKECASE(x) case (x): pName = #x; break;
2518 switch (pEvent)
2519 {
2526 default:
2527 break;
2528 }
2529 ParaNdis_DebugHistory(pContext, hopPnpEvent, NULL, pEvent, 0, 0);
2530 DPrintf(0, ("[%s] (%s)", __FUNCTION__, pName));
2532 {
2533 // on simulated surprise removal (under PnpTest) we need to reset the device
2534 // to prevent any access of device queues to memory buffers
2535 pContext->bSurprizeRemoved = TRUE;
2537 }
2538 pContext->PnpEvents[pContext->nPnpEventIndex++] = pEvent;
2539 if (pContext->nPnpEventIndex > sizeof(pContext->PnpEvents)/sizeof(pContext->PnpEvents[0]))
2540 pContext->nPnpEventIndex = 0;
2541}
2542
2544 PARANDIS_ADAPTER *pContext,
2545 UCHAR cls,
2546 UCHAR cmd,
2547 PVOID buffer1,
2548 ULONG size1,
2549 PVOID buffer2,
2550 ULONG size2,
2551 int levelIfOK
2552 )
2553{
2554 BOOLEAN bOK = FALSE;
2555 NdisAcquireSpinLock(&pContext->ReceiveLock);
2556 if (pContext->ControlData.Virtual && pContext->ControlData.size > (size1 + size2 + 16))
2557 {
2558 struct VirtIOBufferDescriptor sg[4];
2559 PUCHAR pBase = (PUCHAR)pContext->ControlData.Virtual;
2560 PHYSICAL_ADDRESS phBase = pContext->ControlData.Physical;
2561 ULONG offset = 0;
2562 UINT nOut = 1;
2563
2564 ((virtio_net_ctrl_hdr *)pBase)->class_of_command = cls;
2565 ((virtio_net_ctrl_hdr *)pBase)->cmd = cmd;
2566 sg[0].physAddr = phBase;
2567 sg[0].length = sizeof(virtio_net_ctrl_hdr);
2568 offset += sg[0].length;
2569 offset = (offset + 3) & ~3;
2570 if (size1)
2571 {
2572 NdisMoveMemory(pBase + offset, buffer1, size1);
2573 sg[nOut].physAddr = phBase;
2574 sg[nOut].physAddr.QuadPart += offset;
2575 sg[nOut].length = size1;
2576 offset += size1;
2577 offset = (offset + 3) & ~3;
2578 nOut++;
2579 }
2580 if (size2)
2581 {
2582 NdisMoveMemory(pBase + offset, buffer2, size2);
2583 sg[nOut].physAddr = phBase;
2584 sg[nOut].physAddr.QuadPart += offset;
2585 sg[nOut].length = size2;
2586 offset += size2;
2587 offset = (offset + 3) & ~3;
2588 nOut++;
2589 }
2590 sg[nOut].physAddr = phBase;
2591 sg[nOut].physAddr.QuadPart += offset;
2592 sg[nOut].length = sizeof(virtio_net_ctrl_ack);
2594
2595 if (0 <= virtqueue_add_buf(pContext->NetControlQueue, sg, nOut, 1, (PVOID)1, NULL, 0))
2596 {
2597 UINT len;
2598 void *p;
2600 p = virtqueue_get_buf(pContext->NetControlQueue, &len);
2601 if (!p)
2602 {
2603 DPrintf(0, ("%s - ERROR: get_buf failed", __FUNCTION__));
2604 }
2605 else if (len != sizeof(virtio_net_ctrl_ack))
2606 {
2607 DPrintf(0, ("%s - ERROR: wrong len %d", __FUNCTION__, len));
2608 }
2609 else if (*(virtio_net_ctrl_ack *)(pBase + offset) != VIRTIO_NET_OK)
2610 {
2611 DPrintf(0, ("%s - ERROR: error %d returned", __FUNCTION__, *(virtio_net_ctrl_ack *)(pBase + offset)));
2612 }
2613 else
2614 {
2615 // everything is OK
2616 DPrintf(levelIfOK, ("%s OK(%d.%d,buffers of %d and %d) ", __FUNCTION__, cls, cmd, size1, size2));
2617 bOK = TRUE;
2618 }
2619 }
2620 else
2621 {
2622 DPrintf(0, ("%s - ERROR: add_buf failed", __FUNCTION__));
2623 }
2624 }
2625 else
2626 {
2627 DPrintf(0, ("%s (buffer %d,%d) - ERROR: message too LARGE", __FUNCTION__, size1, size2));
2628 }
2629 NdisReleaseSpinLock(&pContext->ReceiveLock);
2630 return bOK;
2631}
2632
2634{
2635 u8 val;
2636 ULONG f = pContext->PacketFilter;
2637 val = (f & NDIS_PACKET_TYPE_ALL_MULTICAST) ? 1 : 0;
2639 //SendControlMessage(pContext, VIRTIO_NET_CTRL_RX_MODE, VIRTIO_NET_CTRL_RX_MODE_ALLUNI, &val, sizeof(val), NULL, 0, 2);
2642 val = (f & NDIS_PACKET_TYPE_DIRECTED) ? 0 : 1;
2644 val = (f & NDIS_PACKET_TYPE_BROADCAST) ? 0 : 1;
2646 val = (f & NDIS_PACKET_TYPE_PROMISCUOUS) ? 1 : 0;
2648}
2649
2651{
2652 struct
2653 {
2656 } uCast;
2657 uCast.header.entries = 1;
2658 NdisMoveMemory(uCast.addr, pContext->CurrentMacAddress, sizeof(uCast.addr));
2660 &uCast, sizeof(uCast), &pContext->MulticastData,sizeof(pContext->MulticastData.nofMulticastEntries) + pContext->MulticastData.nofMulticastEntries * ETH_ALEN, 2);
2661}
2662
2663static VOID SetSingleVlanFilter(PARANDIS_ADAPTER *pContext, ULONG vlanId, BOOLEAN bOn, int levelIfOK)
2664{
2665 u16 val = vlanId & 0xfff;
2667 SendControlMessage(pContext, VIRTIO_NET_CTRL_VLAN, cmd, &val, sizeof(val), NULL, 0, levelIfOK);
2668}
2669
2671{
2672 ULONG i;
2673 for (i = 0; i <= MAX_VLAN_ID; ++i)
2674 SetSingleVlanFilter(pContext, i, bOn, 7);
2675}
2676
2677/*
2678 possible values of filter set (pContext->ulCurrentVlansFilterSet):
2679 0 - all disabled
2680 1..4095 - one selected enabled
2681 4096 - all enabled
2682 Note that only 0th vlan can't be enabled
2683*/
2685{
2686 if (pContext->bHasHardwareFilters)
2687 {
2688 ULONG newFilterSet;
2689 if (IsVlanSupported(pContext))
2690 newFilterSet = pContext->VlanId ? pContext->VlanId : (MAX_VLAN_ID + 1);
2691 else
2692 newFilterSet = IsPrioritySupported(pContext) ? (MAX_VLAN_ID + 1) : 0;
2693 if (newFilterSet != pContext->ulCurrentVlansFilterSet)
2694 {
2695 if (pContext->ulCurrentVlansFilterSet > MAX_VLAN_ID)
2696 SetAllVlanFilters(pContext, FALSE);
2697 else if (pContext->ulCurrentVlansFilterSet)
2698 SetSingleVlanFilter(pContext, pContext->ulCurrentVlansFilterSet, FALSE, 2);
2699
2700 pContext->ulCurrentVlansFilterSet = newFilterSet;
2701
2702 if (pContext->ulCurrentVlansFilterSet > MAX_VLAN_ID)
2703 SetAllVlanFilters(pContext, TRUE);
2704 else if (pContext->ulCurrentVlansFilterSet)
2705 SetSingleVlanFilter(pContext, pContext->ulCurrentVlansFilterSet, TRUE, 2);
2706 }
2707 }
2708}
2709
2711{
2712 if (pContext->bHasHardwareFilters)
2713 {
2717 }
2718}
2719
2721{
2722 LIST_ENTRY TempList;
2724 DEBUG_ENTRY(0);
2725 ParaNdis_DebugHistory(pContext, hopPowerOn, NULL, 1, 0, 0);
2728 /* virtio_get_features must be called once upon device initialization:
2729 otherwise the device will not work properly */
2730 (void)virtio_get_features(&pContext->IODevice);
2731
2732 if (pContext->bUseMergedBuffers)
2736 if (pContext->bDoGuestChecksumOnReceive)
2742
2743 status = FinalizeFeatures(pContext);
2744 if (status == NDIS_STATUS_SUCCESS) {
2745 status = FindNetQueues(pContext);
2746 }
2747 if (status != NDIS_STATUS_SUCCESS) {
2749 return status;
2750 }
2751
2753
2755
2756 InitializeListHead(&TempList);
2757
2758 /* submit all the receive buffers */
2759 NdisAcquireSpinLock(&pContext->ReceiveLock);
2760
2762
2763 while (!IsListEmpty(&pContext->NetReceiveBuffers))
2764 {
2765 pIONetDescriptor pBufferDescriptor =
2767 InsertTailList(&TempList, &pBufferDescriptor->listEntry);
2768 }
2769 pContext->NetNofReceiveBuffers = 0;
2770 while (!IsListEmpty(&TempList))
2771 {
2772 pIONetDescriptor pBufferDescriptor =
2773 (pIONetDescriptor)RemoveHeadList(&TempList);
2774 if (AddRxBufferToQueue(pContext, pBufferDescriptor))
2775 {
2776 InsertTailList(&pContext->NetReceiveBuffers, &pBufferDescriptor->listEntry);
2777 pContext->NetNofReceiveBuffers++;
2778 }
2779 else
2780 {
2781 DPrintf(0, ("FAILED TO REUSE THE BUFFER!!!!"));
2782 VirtIONetFreeBufferDescriptor(pContext, pBufferDescriptor);
2783 pContext->NetMaxReceiveBuffers--;
2784 }
2785 }
2789 virtio_device_ready(&pContext->IODevice);
2790
2791 NdisReleaseSpinLock(&pContext->ReceiveLock);
2792
2793 // if bFastSuspendInProcess is set by Win8 power-off procedure,
2794 // the ParaNdis_Resume enables Tx and RX
2795 // otherwise it does not do anything in Vista+ (Tx and RX are enabled after power-on by Restart)
2796 ParaNdis_Resume(pContext);
2797 pContext->bFastSuspendInProcess = FALSE;
2798
2800 ParaNdis_DebugHistory(pContext, hopPowerOn, NULL, 0, 0, 0);
2801
2802 return status;
2803}
2804
2806{
2807 DEBUG_ENTRY(0);
2808 ParaNdis_DebugHistory(pContext, hopPowerOff, NULL, 1, 0, 0);
2809
2811
2812 // if bFastSuspendInProcess is set by Win8 power-off procedure
2813 // the ParaNdis_Suspend does fast Rx stop without waiting (=>srsPausing, if there are some RX packets in Ndis)
2814 pContext->bFastSuspendInProcess = pContext->bNoPauseOnSuspend && pContext->ReceiveState == srsEnabled;
2815 ParaNdis_Suspend(pContext);
2816 if (pContext->IODevice.addr)
2817 {
2818 /* back compat - remove the OK flag only in legacy mode */
2820 }
2821
2822 if (pContext->bFastSuspendInProcess)
2823 {
2824 NdisAcquireSpinLock(&pContext->ReceiveLock);
2826 NdisReleaseSpinLock(&pContext->ReceiveLock);
2827 }
2828
2830
2831 PreventDPCServicing(pContext);
2832
2833 /*******************************************************************
2834 shutdown queues to have all the receive buffers under our control
2835 all the transmit buffers move to list of free buffers
2836 ********************************************************************/
2837
2838 NdisAcquireSpinLock(&pContext->SendLock);
2840 while (!IsListEmpty(&pContext->NetSendBuffersInUse))
2841 {
2842 pIONetDescriptor pBufferDescriptor =
2844 InsertTailList(&pContext->NetFreeSendBuffers, &pBufferDescriptor->listEntry);
2845 pContext->nofFreeTxDescriptors++;
2846 pContext->nofFreeHardwareBuffers += pBufferDescriptor->nofUsedBuffers;
2847 }
2848 NdisReleaseSpinLock(&pContext->SendLock);
2849
2850 NdisAcquireSpinLock(&pContext->ReceiveLock);
2852 NdisReleaseSpinLock(&pContext->ReceiveLock);
2853 if (pContext->NetControlQueue) {
2855 }
2856
2857 DPrintf(0, ("WARNING: deleting queues!!!!!!!!!"));
2858 DeleteNetQueues(pContext);
2859 pContext->NetSendQueue = NULL;
2860 pContext->NetReceiveQueue = NULL;
2861 pContext->NetControlQueue = NULL;
2862
2864 ParaNdis_DebugHistory(pContext, hopPowerOff, NULL, 0, 0, 0);
2865}
2866
2868{
2869 if (pContext->IODevice.isr)
2870 {
2871#ifdef DBG_USE_VIRTIO_PCI_ISR_FOR_HOST_REPORT
2872 WriteVirtIODeviceByte(pContext->IODevice.isr, 1);
2873#endif
2874 }
2875}
2876
2878{
2881 PVOID pIpHeader = RtlOffsetToPointer(pRxPacket, ETH_HEADER_SIZE);
2883 ULONG flagsToCalculate = 0;
2884 res.value = 0;
2885 resIp.value = 0;
2886
2887 //VIRTIO_NET_HDR_F_NEEDS_CSUM - we need to calculate TCP/UDP CS
2888 //VIRTIO_NET_HDR_F_DATA_VALID - host tells us TCP/UDP CS is OK
2889
2890 if (f.fRxIPChecksum) flagsToCalculate |= pcrIpChecksum; // check only
2891
2892 if (!(virtioFlags & VIRTIO_NET_HDR_F_DATA_VALID))
2893 {
2894 if (virtioFlags & VIRTIO_NET_HDR_F_NEEDS_CSUM)
2895 {
2896 flagsToCalculate |= pcrFixXxpChecksum | pcrTcpChecksum | pcrUdpChecksum;
2897 }
2898 else
2899 {
2900 if (f.fRxTCPChecksum) flagsToCalculate |= pcrTcpV4Checksum;
2901 if (f.fRxUDPChecksum) flagsToCalculate |= pcrUdpV4Checksum;
2902 if (f.fRxTCPv6Checksum) flagsToCalculate |= pcrTcpV6Checksum;
2903 if (f.fRxUDPv6Checksum) flagsToCalculate |= pcrUdpV6Checksum;
2904 }
2905 }
2906
2907 ppr = ParaNdis_CheckSumVerify(pIpHeader, len - ETH_HEADER_SIZE, flagsToCalculate, __FUNCTION__);
2908
2909 if (virtioFlags & VIRTIO_NET_HDR_F_DATA_VALID)
2910 {
2911 pContext->extraStatistics.framesRxCSHwOK++;
2912 ppr.xxpCheckSum = ppresCSOK;
2913 }
2914
2915 if (ppr.ipStatus == ppresIPV4 && !ppr.IsFragment)
2916 {
2917 if (f.fRxIPChecksum)
2918 {
2919 res.flags.IpOK = ppr.ipCheckSum == ppresCSOK;
2920 res.flags.IpFailed = ppr.ipCheckSum == ppresCSBad;
2921 }
2922 if(ppr.xxpStatus == ppresXxpKnown)
2923 {
2924 if(ppr.TcpUdp == ppresIsTCP) /* TCP */
2925 {
2926 if (f.fRxTCPChecksum)
2927 {
2928 res.flags.TcpOK = ppr.xxpCheckSum == ppresCSOK || ppr.fixedXxpCS;
2929 res.flags.TcpFailed = !res.flags.TcpOK;
2930 }
2931 }
2932 else /* UDP */
2933 {
2934 if (f.fRxUDPChecksum)
2935 {
2936 res.flags.UdpOK = ppr.xxpCheckSum == ppresCSOK || ppr.fixedXxpCS;
2937 res.flags.UdpFailed = !res.flags.UdpOK;
2938 }
2939 }
2940 }
2941 }
2942 else if (ppr.ipStatus == ppresIPV6)
2943 {
2944 if(ppr.xxpStatus == ppresXxpKnown)
2945 {
2946 if(ppr.TcpUdp == ppresIsTCP) /* TCP */
2947 {
2948 if (f.fRxTCPv6Checksum)
2949 {
2950 res.flags.TcpOK = ppr.xxpCheckSum == ppresCSOK || ppr.fixedXxpCS;
2951 res.flags.TcpFailed = !res.flags.TcpOK;
2952 }
2953 }
2954 else /* UDP */
2955 {
2956 if (f.fRxUDPv6Checksum)
2957 {
2958 res.flags.UdpOK = ppr.xxpCheckSum == ppresCSOK || ppr.fixedXxpCS;
2959 res.flags.UdpFailed = !res.flags.UdpOK;
2960 }
2961 }
2962 }
2963 }
2964
2965 if (pContext->bDoIPCheckRx &&
2966 (f.fRxIPChecksum || f.fRxTCPChecksum || f.fRxUDPChecksum || f.fRxTCPv6Checksum || f.fRxUDPv6Checksum))
2967 {
2969 if (ppr.ipStatus == ppresIPV4 && !ppr.IsFragment)
2970 {
2971 resIp.flags.IpOK = !!f.fRxIPChecksum && ppr.ipCheckSum == ppresCSOK;
2972 resIp.flags.IpFailed = !!f.fRxIPChecksum && ppr.ipCheckSum == ppresCSBad;
2973 if (f.fRxTCPChecksum && ppr.xxpStatus == ppresXxpKnown && ppr.TcpUdp == ppresIsTCP)
2974 {
2975 resIp.flags.TcpOK = ppr.xxpCheckSum == ppresCSOK;
2976 resIp.flags.TcpFailed = ppr.xxpCheckSum == ppresCSBad;
2977 }
2978 if (f.fRxUDPChecksum && ppr.xxpStatus == ppresXxpKnown && ppr.TcpUdp == ppresIsUDP)
2979 {
2980 resIp.flags.UdpOK = ppr.xxpCheckSum == ppresCSOK;
2981 resIp.flags.UdpFailed = ppr.xxpCheckSum == ppresCSBad;
2982 }
2983 }
2984 else if (ppr.ipStatus == ppresIPV6)
2985 {
2986 if (f.fRxTCPv6Checksum && ppr.xxpStatus == ppresXxpKnown && ppr.TcpUdp == ppresIsTCP)
2987 {
2988 resIp.flags.TcpOK = ppr.xxpCheckSum == ppresCSOK;
2989 resIp.flags.TcpFailed = ppr.xxpCheckSum == ppresCSBad;
2990 }
2991 if (f.fRxUDPv6Checksum && ppr.xxpStatus == ppresXxpKnown && ppr.TcpUdp == ppresIsUDP)
2992 {
2993 resIp.flags.UdpOK = ppr.xxpCheckSum == ppresCSOK;
2994 resIp.flags.UdpFailed = ppr.xxpCheckSum == ppresCSBad;
2995 }
2996 }
2997
2998 if (res.value != resIp.value)
2999 {
3000 // if HW did not set some bits that IP checker set, it is a mistake:
3001 // or GOOD CS is not labeled, or BAD checksum is not labeled
3003 diff.value = resIp.value & ~res.value;
3004 if (diff.flags.IpFailed || diff.flags.TcpFailed || diff.flags.UdpFailed)
3005 pContext->extraStatistics.framesRxCSHwMissedBad++;
3006 if (diff.flags.IpOK || diff.flags.TcpOK || diff.flags.UdpOK)
3007 pContext->extraStatistics.framesRxCSHwMissedGood++;
3008 if (diff.value)
3009 {
3010 DPrintf(0, ("[%s] real %X <> %X (virtio %X)", __FUNCTION__, resIp.value, res.value, virtioFlags));
3011 }
3012 res.value = resIp.value;
3013 }
3014 }
3015
3016 return res;
3017}
@ hopInternalReceivePause
Definition: DebugData.h:45
@ hopReceiveStat
Definition: DebugData.h:58
@ hopPnpEvent
Definition: DebugData.h:64
@ hopPowerOff
Definition: DebugData.h:40
@ hopDPC
Definition: DebugData.h:51
@ hopPowerOn
Definition: DebugData.h:41
#define PARANDIS_STORE_LAST_INTERRUPT_TIMESTAMP(p)
Definition: DebugData.h:107
#define VIRTIO_NET_HDR_F_DATA_VALID
#define VIRTIO_NET_CTRL_MAC_TABLE_SET
struct tag_virtio_net_ctrl_hdr virtio_net_ctrl_hdr
u8 virtio_net_ctrl_ack
struct _tagvirtio_net_hdr virtio_net_hdr_basic
#define VIRTIO_NET_CTRL_RX_MODE_PROMISC
#define VIRTIO_NET_OK
#define VIRTIO_NET_CTRL_MAC
#define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI
#define VIRTIO_NET_CTRL_RX_MODE_NOMULTI
#define VIRTIO_NET_ERR
#define VIRTIO_NET_CTRL_VLAN_ADD
#define VIRTIO_NET_CTRL_VLAN_DEL
#define VIRTIO_NET_CTRL_RX_MODE_NOUNI
struct _tagvirtio_net_hdr_ext virtio_net_hdr_ext
#define VIRTIO_NET_CTRL_VLAN
#define VIRTIO_NET_HDR_F_NEEDS_CSUM
#define VIRTIO_NET_CTRL_RX_MODE
#define VIRTIO_NET_CTRL_RX_MODE_NOBCAST
BOOLEAN ParaNdis_OnLegacyInterrupt(PARANDIS_ADAPTER *pContext, OUT BOOLEAN *pRunDpc)
void ParaNdis_PadPacketReceived(PVOID pDataBuffer, PULONG pLength)
NDIS_STATUS ParaNdis_FinishInitialization(PARANDIS_ADAPTER *pContext)
static void VirtIONetRelease(PARANDIS_ADAPTER *pContext)
static void FreeDescriptorsFromList(PARANDIS_ADAPTER *pContext, PLIST_ENTRY pListRoot, PNDIS_SPIN_LOCK pLock)
static void ReadNicConfiguration(PARANDIS_ADAPTER *pContext, PUCHAR *ppNewMACAddress)
static void ReuseReceiveBufferRegular(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor)
void FORCEINLINE DebugDumpPacket(LPCSTR prefix, PVOID header, int level)
UINT ParaNdis_VirtIONetReleaseTransmitBuffers(PARANDIS_ADAPTER *pContext)
static VOID ParaNdis_DeviceFiltersUpdateAddresses(PARANDIS_ADAPTER *pContext)
BOOLEAN ParaNdis_CheckForHang(PARANDIS_ADAPTER *pContext)
NDIS_STATUS ParaNdis_PowerOn(PARANDIS_ADAPTER *pContext)
VOID ParaNdis_VirtIOEnableIrqSynchronized(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
static BOOLEAN CheckRunningDpc(PARANDIS_ADAPTER *pContext)
static int PrepareReceiveBuffers(PARANDIS_ADAPTER *pContext)
tChecksumCheckResult ParaNdis_CheckRxChecksum(PARANDIS_ADAPTER *pContext, ULONG virtioFlags, PVOID pRxPacket, ULONG len)
VOID ParaNdis_CleanupContext(PARANDIS_ADAPTER *pContext)
static void VirtIODeviceRemoveStatus(VirtIODevice *vdev, u8 status)
#define MAKECASE(x)
static void DumpVirtIOFeatures(PARANDIS_ADAPTER *pContext)
static ULONG FORCEINLINE QueryTcpHeaderOffset(PVOID packetData, ULONG ipHeaderOffset, ULONG ipPacketLength)
VOID ParaNdis_OnPnPEvent(PARANDIS_ADAPTER *pContext, NDIS_DEVICE_PNP_EVENT pEvent, PVOID pInfo, ULONG ulSize)
tCopyPacketResult ParaNdis_DoCopyPacketData(PARANDIS_ADAPTER *pContext, tTxOperationParameters *pParams)
void ParaNdis_ResetOffloadSettings(PARANDIS_ADAPTER *pContext, tOffloadSettingsFlags *pDest, PULONG from)
static BOOLEAN GetAdapterResources(NDIS_HANDLE MiniportHandle, PNDIS_RESOURCE_LIST RList, tAdapterResources *pResources)
static NDIS_STATUS FindNetQueues(PARANDIS_ADAPTER *pContext)
static void GetConfigurationEntry(NDIS_HANDLE cfg, tConfigurationEntry *pEntry)
static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER *pContext, ULONG ulMaxPacketsToIndicate)
VOID ParaNdis_UpdateDeviceFilters(PARANDIS_ADAPTER *pContext)
static void JustForCheckClearInterrupt(PARANDIS_ADAPTER *pContext, const char *Label)
static VOID ParaNdis_DeviceFiltersUpdateRxMode(PARANDIS_ADAPTER *pContext)
static VOID SetSingleVlanFilter(PARANDIS_ADAPTER *pContext, ULONG vlanId, BOOLEAN bOn, int levelIfOK)
static void ReuseReceiveBufferPowerOff(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor)
VOID ParaNdis_PowerOff(PARANDIS_ADAPTER *pContext)
BOOLEAN ParaNdis_ValidateMacAddress(PUCHAR pcMacAddress, BOOLEAN bLocal)
static void VirtIONetFreeBufferDescriptor(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDescriptor)
void ParaNdis_ReportLinkStatus(PARANDIS_ADAPTER *pContext, BOOLEAN bForce)
static void PrepareTransmitBuffers(PARANDIS_ADAPTER *pContext)
static void PreventDPCServicing(PARANDIS_ADAPTER *pContext)
static void DisableLSOv6Permanently(PARANDIS_ADAPTER *pContext, LPCSTR procname, LPCSTR reason)
VOID ParaNdis_DeviceFiltersUpdateVlanId(PARANDIS_ADAPTER *pContext)
BOOLEAN ParaNdis_OnQueuedInterrupt(PARANDIS_ADAPTER *pContext, OUT BOOLEAN *pRunDpc, ULONG knownInterruptSources)
static void ParaNdis_ResetVirtIONetDevice(PARANDIS_ADAPTER *pContext)
static BOOLEAN NTAPI RestartQueueSynchronously(tSynchronizedContext *SyncContext)
VOID ParaNdis_VirtIODisableIrqSynchronized(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
static VOID SetAllVlanFilters(PARANDIS_ADAPTER *pContext, BOOLEAN bOn)
ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext, ULONG ulMaxPacketsToIndicate)
static NDIS_STATUS FinalizeFeatures(PARANDIS_ADAPTER *pContext)
static BOOLEAN AddRxBufferToQueue(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDescriptor)
static void PrintStatistics(PARANDIS_ADAPTER *pContext)
struct _tagConfigurationEntries tConfigurationEntries
VOID ParaNdis_OnShutdown(PARANDIS_ADAPTER *pContext)
struct _tagConfigurationEntry tConfigurationEntry
NDIS_STATUS ParaNdis_InitializeContext(PARANDIS_ADAPTER *pContext, PNDIS_RESOURCE_LIST pResourceList)
#define MAX_VLAN_ID
void ParaNdis_CallOnBugCheck(PARANDIS_ADAPTER *pContext)
static eInspectedPacketType QueryPacketType(PVOID data)
static const tConfigurationEntries defaultConfiguration
NDIS_STATUS ParaNdis_SetMulticastList(PARANDIS_ADAPTER *pContext, PVOID Buffer, ULONG BufferSize, PUINT pBytesRead, PUINT pBytesNeeded)
static BOOLEAN SendControlMessage(PARANDIS_ADAPTER *pContext, UCHAR cls, UCHAR cmd, PVOID buffer1, ULONG size1, PVOID buffer2, ULONG size2, int levelIfOK)
static void DisableLSOv4Permanently(PARANDIS_ADAPTER *pContext, LPCSTR procname, LPCSTR reason)
static void DisableBothLSOPermanently(PARANDIS_ADAPTER *pContext, LPCSTR procname, LPCSTR reason)
static pIONetDescriptor AllocatePairOfBuffersOnInit(PARANDIS_ADAPTER *pContext, ULONG size1, ULONG size2, BOOLEAN bForTx)
static NDIS_STATUS ParaNdis_VirtIONetInit(PARANDIS_ADAPTER *pContext)
tCopyPacketResult ParaNdis_DoSubmitPacket(PARANDIS_ADAPTER *pContext, tTxOperationParameters *Params)
static void DeleteNetQueues(PARANDIS_ADAPTER *pContext)
static NDIS_STATUS NTStatusToNdisStatus(NTSTATUS nt_status)
static ULONG ShallPassPacket(PARANDIS_ADAPTER *pContext, PVOID address, UINT len, eInspectedPacketType *pType)
static void WriteVirtIODeviceByte(ULONG_PTR ulRegister, u8 bValue)
unsigned char BOOLEAN
static bool virtqueue_enable_cb_delayed(struct virtqueue *vq)
Definition: VirtIO.h:100
static int virtqueue_add_buf(struct virtqueue *vq, struct scatterlist sg[], unsigned int out_num, unsigned int in_num, void *opaque, void *va_indirect, ULONGLONG phys_indirect)
Definition: VirtIO.h:63
void virtqueue_kick(struct virtqueue *vq)
static void virtqueue_disable_cb(struct virtqueue *vq)
Definition: VirtIO.h:90
static void virtqueue_kick_always(struct virtqueue *vq)
Definition: VirtIO.h:80
static void * virtqueue_get_buf(struct virtqueue *vq, unsigned int *len)
Definition: VirtIO.h:85
static bool virtqueue_enable_cb(struct virtqueue *vq)
Definition: VirtIO.h:95
static void virtqueue_shutdown(struct virtqueue *vq)
Definition: VirtIO.h:120
#define read
Definition: acwin.h:96
struct NameRec_ * Name
Definition: cdprocs.h:460
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
PWCHAR Label
Definition: format.c:70
UCHAR u8
Definition: btrfs.h:12
USHORT u16
Definition: btrfs.h:13
Definition: bufpool.h:45
LPCConfig pConfiguration
Definition: config.cpp:18
#define BufferSize
Definition: mmc.h:75
#define ETH_ALEN
Definition: dhcpd.h:50
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
#define __FUNCTION__
Definition: types.h:116
#define ETH_IS_LOCALLY_ADMINISTERED(Address)
Definition: util.h:19
#define ETH_IS_EMPTY(Address)
Definition: util.h:22
#define DEBUG_ENTRY(level)
Definition: kdebugprint.h:49
#define DPrintf(Level, Fmt)
Definition: kdebugprint.h:61
#define DEBUG_EXIT_STATUS(level, status)
Definition: kdebugprint.h:50
int nDebugLevel
int bDebugPrint
VOID EXPORT NdisCloseConfiguration(IN NDIS_HANDLE ConfigurationHandle)
Definition: config.c:136
VOID EXPORT NdisReadConfiguration(OUT PNDIS_STATUS Status, OUT PNDIS_CONFIGURATION_PARAMETER *ParameterValue, IN NDIS_HANDLE ConfigurationHandle, IN PNDIS_STRING Keyword, IN NDIS_PARAMETER_TYPE ParameterType)
Definition: config.c:414
VOID EXPORT NdisReadNetworkAddress(OUT PNDIS_STATUS Status, OUT PVOID *NetworkAddress, OUT PUINT NetworkAddressLength, IN NDIS_HANDLE ConfigurationHandle)
Definition: config.c:740
VOID EXPORT NdisInitializeEvent(IN PNDIS_EVENT Event)
Definition: control.c:221
ULONG EXPORT NdisReadPciSlotInformation(IN NDIS_HANDLE NdisAdapterHandle, IN ULONG SlotNumber, IN ULONG Offset, IN PVOID Buffer, IN ULONG Length)
Definition: hardware.c:180
VOID EXPORT NdisMDeregisterIoPortRange(IN NDIS_HANDLE MiniportAdapterHandle, IN UINT InitialPort, IN UINT NumberOfPorts, IN PVOID PortOffset)
Definition: io.c:1093
VOID EXPORT NdisMUnmapIoSpace(IN NDIS_HANDLE MiniportAdapterHandle, IN PVOID VirtualAddress, IN UINT Length)
Definition: io.c:1139
VOID EXPORT NdisFreeMemory(IN PVOID VirtualAddress, IN UINT Length, IN UINT MemoryFlags)
Definition: memory.c:110
VOID EXPORT NdisMFreeSharedMemory(IN NDIS_HANDLE MiniportAdapterHandle, IN ULONG Length, IN BOOLEAN Cached, IN PVOID VirtualAddress, IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
Definition: memory.c:215
VOID EXPORT NdisInitializeString(IN OUT PNDIS_STRING DestinationString, IN PUCHAR SourceString)
Definition: string.c:101
#define ETH_LENGTH_OF_ADDRESS
Definition: efilter.h:16
void bar()
Definition: ehthrow.cxx:142
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ETH_HEADER_SIZE
Definition: ethernetutils.h:53
enum _tag_eInspectedPacketType eInspectedPacketType
@ iptUnicast
Definition: ethernetutils.h:69
@ iptMulticast
Definition: ethernetutils.h:71
@ iptBroadcast
Definition: ethernetutils.h:70
@ iptInvalid
Definition: ethernetutils.h:72
#define TCP_CHECKSUM_OFFSET
#define ETH_PRIORITY_HEADER_SIZE
Definition: ethernetutils.h:56
#define ETH_HAS_PRIO_HEADER(Address)
Definition: ethernetutils.h:41
#define UDP_CHECKSUM_OFFSET
#define ETH_MIN_PACKET_SIZE
Definition: ethernetutils.h:54
BOOL bConnected
Definition: fdebug.c:27
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
FxSpinLock * pLock
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLuint address
Definition: glext.h:9393
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CmResourceTypeMemory
Definition: hwresource.cpp:125
#define CmResourceTypePort
Definition: hwresource.cpp:123
#define CmResourceTypeInterrupt
Definition: hwresource.cpp:124
#define InterlockedOr
Definition: interlocked.h:224
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
unsigned __int64 ULONG64
Definition: imports.h:198
static LPSTR pName
Definition: security.c:75
static IPrintDialogCallback callback
Definition: printdlg.c:326
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:582
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:573
#define min(a, b)
Definition: monoChain.cc:55
@ pcrPriorityTag
Definition: ndis56common.h:882
@ pcrUdpV4Checksum
Definition: ndis56common.h:867
@ pcrLSO
Definition: ndis56common.h:873
@ pcrAnyChecksum
Definition: ndis56common.h:872
@ pcrTcpV4Checksum
Definition: ndis56common.h:866
@ pcrIpChecksum
Definition: ndis56common.h:865
@ pcrTcpV6Checksum
Definition: ndis56common.h:868
@ pcrUdpChecksum
Definition: ndis56common.h:871
@ pcrNoIndirect
Definition: ndis56common.h:883
@ pcrFixIPChecksum
Definition: ndis56common.h:875
@ pcrFixXxpChecksum
Definition: ndis56common.h:881
@ pcrTcpChecksum
Definition: ndis56common.h:870
@ pcrUdpV6Checksum
Definition: ndis56common.h:869
@ osbT4RxTCPChecksum
Definition: ndis56common.h:187
@ osbT4TcpChecksum
Definition: ndis56common.h:180
@ osbT4RxTCPOptionsChecksum
Definition: ndis56common.h:188
@ osbT4Lso
Definition: ndis56common.h:184
@ osbT6Lso
Definition: ndis56common.h:196
@ osbT6UdpChecksum
Definition: ndis56common.h:193
@ osbT4TcpOptionsChecksum
Definition: ndis56common.h:182
@ osbT6RxUDPChecksum
Definition: ndis56common.h:201
@ osbT4LsoIp
Definition: ndis56common.h:185
@ osbT4RxIPOptionsChecksum
Definition: ndis56common.h:190
@ osbT4UdpChecksum
Definition: ndis56common.h:181
@ osbT4IpOptionsChecksum
Definition: ndis56common.h:183
@ osbT4LsoTcp
Definition: ndis56common.h:186
@ osbT6RxTCPChecksum
Definition: ndis56common.h:199
@ osbT6TcpOptionsChecksum
Definition: ndis56common.h:194
@ osbT4RxIPChecksum
Definition: ndis56common.h:189
@ osbT6RxIpExtChecksum
Definition: ndis56common.h:202
@ osbT6LsoIpExt
Definition: ndis56common.h:197
@ osbT6IpExtChecksum
Definition: ndis56common.h:195
@ osbT4RxUDPChecksum
Definition: ndis56common.h:191
@ osbT4IpChecksum
Definition: ndis56common.h:179
@ osbT6TcpChecksum
Definition: ndis56common.h:192
@ osbT6LsoTcpOptions
Definition: ndis56common.h:198
@ osbT6RxTCPOptionsChecksum
Definition: ndis56common.h:200
tTcpIpPacketParsingResult ParaNdis_CheckSumVerify(PVOID buffer, ULONG size, ULONG flags, LPCSTR caller)
Definition: sw-offload.c:565
#define VIRTIO_NET_F_CSUM
Definition: ndis56common.h:96
@ srsEnabled
Definition: ndis56common.h:157
@ srsDisabled
Definition: ndis56common.h:155
@ srsPausing
Definition: ndis56common.h:156
VOID ParaNdis_FreePhysicalMemory(PARANDIS_ADAPTER *pContext, tCompletePhysicalAddress *pAddresses)
tTcpIpPacketParsingResult ParaNdis_ReviewIPPacket(PVOID buffer, ULONG size, LPCSTR caller)
Definition: sw-offload.c:614
#define VIRTIO_NET_F_GUEST_TSO4
Definition: ndis56common.h:100
static void VirtIODeviceEnableGuestFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
Definition: ndis56common.h:521
NDIS_HANDLE ParaNdis_OpenNICConfiguration(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_F_GSO
Definition: ndis56common.h:99
#define RtlOffsetToPointer(Base, Offset)
Definition: ndis56common.h:50
VOID ParaNdis_PacketMapper(PARANDIS_ADAPTER *pContext, tPacketType packet, PVOID Reference, struct VirtIOBufferDescriptor *buffers, pIONetDescriptor pDesc, tMapperResult *pMapperResult)
tCopyPacketResult ParaNdis_PacketCopier(tPacketType packet, PVOID dest, ULONG maxSize, PVOID refValue, BOOLEAN bPreview)
VOID ParaNdis_OnTransmitBufferReleased(PARANDIS_ADAPTER *pContext, IONetDescriptor *pDesc)
#define VIRTIO_NET_F_HOST_TSO4
Definition: ndis56common.h:104
PVOID ParaNdis_AllocateMemory(PARANDIS_ADAPTER *pContext, ULONG ulRequiredSize)
void(* tReuseReceiveBufferProc)(void *pContext, pIONetDescriptor pDescriptor)
Definition: ndis56common.h:344
VOID ParaNdis_Resume(PARANDIS_ADAPTER *pContext)
VOID ParaNdis_IndicateReceivedBatch(PARANDIS_ADAPTER *pContext, tPacketIndicationType *pBatch, ULONG nofPackets)
#define VIRTIO_NET_F_GUEST_CSUM
Definition: ndis56common.h:97
#define VIRTIO_NET_F_GUEST_ECN
Definition: ndis56common.h:102
BOOLEAN ParaNdis_InitialAllocatePhysicalMemory(PARANDIS_ADAPTER *pContext, tCompletePhysicalAddress *pAddresses)
#define PARANDIS_UNLIMITED_PACKETS_TO_INDICATE
Definition: ndis56common.h:128
VOID ParaNdis_SetPowerState(PARANDIS_ADAPTER *pContext, NDIS_DEVICE_POWER_STATE newState)
tPacketIndicationType ParaNdis_IndicateReceivedPacket(PARANDIS_ADAPTER *pContext, PVOID dataBuffer, PULONG pLength, BOOLEAN bPrepareOnly, pIONetDescriptor pBufferDesc)
#define MAX_RX_LOOPS
Definition: ndis56common.h:90
#define VIRTIO_NET_S_LINK_UP
Definition: ndis56common.h:115
static BOOLEAN FORCEINLINE IsPrioritySupported(PARANDIS_ADAPTER *pContext)
Definition: ndis56common.h:547
#define VIRTIO_NET_F_GUEST_TSO6
Definition: ndis56common.h:101
@ cpeInternalError
Definition: ndis56common.h:490
@ cpeNoIndirect
Definition: ndis56common.h:490
@ cpeOK
Definition: ndis56common.h:490
@ cpeNoBuffer
Definition: ndis56common.h:490
@ cpeTooLarge
Definition: ndis56common.h:490
static BOOLEAN FORCEINLINE IsVlanSupported(PARANDIS_ADAPTER *pContext)
Definition: ndis56common.h:542
@ isTransmit
Definition: ndis56common.h:136
@ isAny
Definition: ndis56common.h:139
@ isReceive
Definition: ndis56common.h:135
@ isControl
Definition: ndis56common.h:134
static __inline struct virtqueue * ParaNdis_GetQueueForInterrupt(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
Definition: ndis56common.h:590
#define VIRTIO_NET_F_HOST_UFO
Definition: ndis56common.h:107
#define VIRTIO_NET_F_HOST_TSO6
Definition: ndis56common.h:105
#define VIRTIO_NET_F_MRG_RXBUF
Definition: ndis56common.h:108
void ParaNdis_IndicateConnect(PARANDIS_ADAPTER *pContext, BOOLEAN bConnected, BOOLEAN bForce)
#define VIRTIO_NET_F_CTRL_VQ
Definition: ndis56common.h:110
BOOLEAN ParaNdis_SynchronizeWithInterrupt(PARANDIS_ADAPTER *pContext, ULONG messageId, tSynchronizedProcedure procedure, PVOID parameter)
#define VIRTIO_NET_F_HOST_ECN
Definition: ndis56common.h:106
VirtIOSystemOps ParaNdisSystemOps
#define VIRTIO_NET_F_CTRL_RX
Definition: ndis56common.h:111
@ ppresCSBad
Definition: ndis56common.h:831
@ ppresIsTCP
Definition: ndis56common.h:835
@ ppresIsUDP
Definition: ndis56common.h:836
@ ppresIPV4
Definition: ndis56common.h:826
@ ppresXxpKnown
Definition: ndis56common.h:833
@ ppresCSOK
Definition: ndis56common.h:830
@ ppresIPV6
Definition: ndis56common.h:827
VOID ParaNdis_FinalizeCleanup(PARANDIS_ADAPTER *pContext)
NDIS_STATUS NTAPI ParaNdis_FinishSpecificInitialization(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_F_STATUS
Definition: ndis56common.h:109
struct _tagIONetDescriptor * pIONetDescriptor
#define VIRTIO_NET_F_CTRL_VLAN
Definition: ndis56common.h:112
void ParaNdis_RestoreDeviceConfigurationAfterReset(PARANDIS_ADAPTER *pContext)
VOID(* ONPAUSECOMPLETEPROC)(VOID *)
Definition: ndis56common.h:150
#define VIRTIO_NET_INVALID_INTERRUPT_STATUS
Definition: ndis56common.h:117
void ParaNdis_UnbindBufferFromPacket(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDesc)
VOID ParaNdis_Suspend(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_F_GUEST_UFO
Definition: ndis56common.h:103
static __inline BOOLEAN ParaNDIS_IsQueueInterruptEnabled(struct virtqueue *_vq)
Definition: ndis56common.h:601
BOOLEAN ParaNdis_BindBufferToPacket(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDesc)
#define VIRTIO_NET_F_CTRL_RX_EXTRA
Definition: ndis56common.h:113
static bool VirtIODeviceGetHostFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
Definition: ndis56common.h:514
static void FORCEINLINE ParaNdis_DebugHistory(PARANDIS_ADAPTER *pContext, eHistoryLogOperation op, PVOID pParam1, ULONG lParam2, ULONG lParam3, ULONG lParam4)
Definition: ndis56common.h:647
#define VIRTIO_NET_F_MAC
Definition: ndis56common.h:98
#define MAX_NUM_OF_QUEUES
Definition: ndis56common.h:93
#define PARANDIS_MAX_LSO_SIZE
Definition: ndis56common.h:126
BOOLEAN ParaNdis_ProcessTx(PARANDIS_ADAPTER *pContext, BOOLEAN IsDpc, BOOLEAN IsInterrupt)
enum _NDIS_DEVICE_PNP_EVENT NDIS_DEVICE_PNP_EVENT
@ NdisDevicePnPEventRemoved
Definition: ndis.h:1001
@ NdisDevicePnPEventQueryStopped
Definition: ndis.h:1003
@ NdisDevicePnPEventPowerProfileChanged
Definition: ndis.h:1005
@ NdisDevicePnPEventStopped
Definition: ndis.h:1004
@ NdisDevicePnPEventQueryRemoved
Definition: ndis.h:1000
@ NdisDevicePnPEventSurpriseRemoved
Definition: ndis.h:1002
#define NDIS_STATUS_INVALID_DEVICE_REQUEST
Definition: ndis.h:510
_Must_inspect_result_ _Out_ PNDIS_STATUS _Out_ PNDIS_CONFIGURATION_PARAMETER _In_ NDIS_HANDLE _In_ PNDIS_STRING _In_ NDIS_PARAMETER_TYPE ParameterType
Definition: ndis.h:4417
#define NdisReleaseSpinLock(_SpinLock)
Definition: ndis.h:4115
#define NDIS_PACKET_TYPE_PROMISCUOUS
Definition: ndis.h:668
@ NdisParameterInteger
Definition: ndis.h:926
#define NdisZeroMemory(Destination, Length)
Definition: ndis.h:3926
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
#define NDIS_STATUS_RESOURCE_CONFLICT
Definition: ndis.h:495
#define NDIS_STATUS_INVALID_LENGTH
Definition: ndis.h:485
#define NdisAllocateSpinLock(_SpinLock)
Definition: ndis.h:4088
#define NDIS_STATUS_FAILURE
Definition: ndis.h:465
#define NdisGetCurrentSystemTime
Definition: ndis.h:4462
#define NDIS_PACKET_TYPE_BROADCAST
Definition: ndis.h:666
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
#define NDIS_PACKET_TYPE_MULTICAST
Definition: ndis.h:664
#define NDIS_PACKET_TYPE_DIRECTED
Definition: ndis.h:663
enum _NDIS_PARAMETER_TYPE NDIS_PARAMETER_TYPE
#define NDIS_PACKET_TYPE_ALL_MULTICAST
Definition: ndis.h:665
#define NDIS_STATUS_ADAPTER_NOT_FOUND
Definition: ndis.h:470
#define NdisFreeSpinLock(_SpinLock)
Definition: ndis.h:4097
#define NdisAcquireSpinLock(_SpinLock)
Definition: ndis.h:4106
#define NdisFreeString(_s)
Definition: ndis.h:4076
#define NdisMoveMemory(Destination, Source, Length)
Definition: ndis.h:3896
#define NDIS_STATUS_RESOURCES
Definition: ndis.h:466
#define NDIS_STATUS_MULTICAST_FULL
Definition: ndis.h:473
#define CM_RESOURCE_INTERRUPT_MESSAGE
Definition: cmtypes.h:145
VOID EXPORT NdisMSleep(IN ULONG MicrosecondsToSleep)
Definition: miniport.c:2928
int NDIS_STATUS
Definition: ntddndis.h:475
@ NdisDeviceStateD0
Definition: ntddndis.h:38
@ NdisDeviceStateD3
Definition: ntddndis.h:41
static HANDLE proc()
Definition: pdb.c:34
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:341
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
CardRegion * from
Definition: spigame.cpp:19
Definition: lan.h:33
PHYSICAL_ADDRESS physAddr
Definition: VirtIO.h:9
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393::@396 Interrupt
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393::@398 Memory
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393::@395 Port
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
Definition: typedefs.h:120
union _NDIS_CONFIGURATION_PARAMETER::@2097 ParameterData
KSPIN_LOCK SpinLock
Definition: ndis.h:330
tBusResource PciBars[PCI_TYPE0_ADDRESSES]
Definition: ndis56common.h:170
NDIS_PHYSICAL_ADDRESS BasePA
Definition: ndis56common.h:161
BOOLEAN bPortSpace
Definition: ndis56common.h:164
struct _tagChecksumCheckResult::@991::@993 flags
PHYSICAL_ADDRESS Physical
Definition: ndis56common.h:322
tConfigurationEntry IPPacketsCheck
tConfigurationEntry OffloadGuestCS
tConfigurationEntry OffloadTxLSO
tConfigurationEntry isPromiscuous
tConfigurationEntry stdTcpcsV6
tConfigurationEntry VlanId
tConfigurationEntry RxCapacity
tConfigurationEntry ConnectRate
tConfigurationEntry LogStatistics
tConfigurationEntry stdUdpcsV4
tConfigurationEntry MTU
tConfigurationEntry InterruptRecovery
tConfigurationEntry PrioritySupport
tConfigurationEntry Indirect
tConfigurationEntry connectTimer
tConfigurationEntry UseSwTxChecksum
tConfigurationEntry ScatterGather
tConfigurationEntry stdLsoV1
tConfigurationEntry isLogEnabled
tConfigurationEntry NumberOfHandledRXPackersInDPC
tConfigurationEntry OffloadRxCS
tConfigurationEntry TxCapacity
tConfigurationEntry stdTcpcsV4
tConfigurationEntry stdLsoV2ip6
tConfigurationEntry stdLsoV2ip4
tConfigurationEntry BatchReceive
tConfigurationEntry debugLevel
tConfigurationEntry PriorityVlanTagging
tConfigurationEntry PacketFiltering
tConfigurationEntry UseMergeableBuffers
tConfigurationEntry OffloadTxChecksum
tConfigurationEntry dpcChecker
tConfigurationEntry stdUdpcsV6
tConfigurationEntry stdIpcsV4
LIST_ENTRY listEntry
Definition: ndis56common.h:336
tCompletePhysicalAddress HeaderInfo
Definition: ndis56common.h:337
tPacketHolderType pHolder
Definition: ndis56common.h:339
tCompletePhysicalAddress DataInfo
Definition: ndis56common.h:338
USHORT usBuffersMapped
Definition: ndis56common.h:687
USHORT usBufferSpaceUsed
Definition: ndis56common.h:688
UCHAR MulticastList[ETH_LENGTH_OF_ADDRESS *PARANDIS_MULTICAST_LIST_SIZE]
Definition: ndis56common.h:332
ULONG64 ifHCOutMulticastPkts
Definition: ndis56common.h:278
ULONG64 ifHCInBroadcastPkts
Definition: ndis56common.h:271
ULONG64 ifHCOutMulticastOctets
Definition: ndis56common.h:279
ULONG64 ifHCOutBroadcastOctets
Definition: ndis56common.h:281
ULONG64 ifHCInMulticastOctets
Definition: ndis56common.h:270
ULONG64 ifHCInMulticastPkts
Definition: ndis56common.h:269
ULONG64 ifHCInUcastOctets
Definition: ndis56common.h:268
ULONG64 ifHCOutUcastOctets
Definition: ndis56common.h:277
ULONG64 ifHCOutBroadcastPkts
Definition: ndis56common.h:280
ULONG64 ifHCOutUcastPkts
Definition: ndis56common.h:276
ULONG64 ifHCInBroadcastOctets
Definition: ndis56common.h:272
tOffloadSettingsFlags flags
Definition: ndis56common.h:237
NDIS_OFFLOAD_PARAMETERS InitialOffloadParameters
Definition: ndis56common.h:471
NDIS_DEVICE_POWER_STATE powerState
Definition: ndis56common.h:389
tAdapterResources AdapterResources
Definition: ndis56common.h:351
ULONGLONG ullHostFeatures
Definition: ndis56common.h:356
ULONGLONG ulFormalLinkSpeed
Definition: ndis56common.h:396
NDIS_HANDLE MiniportHandle
Definition: ndis56common.h:349
tOurCounters Counters
Definition: ndis56common.h:432
UINT uNumberOfHandledRXPacketsInDPC
Definition: ndis56common.h:388
BOOLEAN bFastSuspendInProcess
Definition: ndis56common.h:384
tOurCounters Limits
Definition: ndis56common.h:433
NDIS_SPIN_LOCK ReceiveLock
Definition: ndis56common.h:412
ONPAUSECOMPLETEPROC ReceivePauseCompletionProc
Definition: ndis56common.h:437
tMulticastData MulticastData
Definition: ndis56common.h:387
NDIS_STATISTICS_INFO Statistics
Definition: ndis56common.h:420
BOOLEAN bIODeviceInitialized
Definition: ndis56common.h:355
BOOLEAN bDoInterruptRecovery
Definition: ndis56common.h:366
BOOLEAN bDoGuestChecksumOnReceive
Definition: ndis56common.h:373
struct virtqueue * NetSendQueue
Definition: ndis56common.h:443
NDIS_DEVICE_PNP_EVENT PnpEvents[16]
Definition: ndis56common.h:469
struct VirtIOBufferDescriptor * sgTxGatherTable
Definition: ndis56common.h:467
NDIS_SPIN_LOCK SendLock
Definition: ndis56common.h:411
BOOLEAN bDoHwPacketFiltering
Definition: ndis56common.h:368
ULONGLONG ullGuestFeatures
Definition: ndis56common.h:357
LIST_ENTRY NetSendBuffersInUse
Definition: ndis56common.h:450
VirtIODevice IODevice
Definition: ndis56common.h:354
tReuseReceiveBufferProc ReuseBufferProc
Definition: ndis56common.h:438
tSendReceiveState ReceiveState
Definition: ndis56common.h:435
BOOLEAN bEnableInterruptChecking
Definition: ndis56common.h:365
BOOLEAN bEnableInterruptHandlingDPC
Definition: ndis56common.h:364
tBusResource SharedMemoryRanges[MAX_NUM_OF_QUEUES]
Definition: ndis56common.h:352
struct _tagPARANDIS_ADAPTER::@994 extraStatistics
UCHAR CurrentMacAddress[ETH_LENGTH_OF_ADDRESS]
Definition: ndis56common.h:402
UCHAR PermanentMacAddress[ETH_LENGTH_OF_ADDRESS]
Definition: ndis56common.h:401
LIST_ENTRY NetFreeSendBuffers
Definition: ndis56common.h:452
BOOLEAN bLinkDetectSupported
Definition: ndis56common.h:371
tCompletePhysicalAddress ControlData
Definition: ndis56common.h:441
LIST_ENTRY NetReceiveBuffers
Definition: ndis56common.h:445
tMaxPacketSize MaxPacketSize
Definition: ndis56common.h:398
struct virtqueue * NetControlQueue
Definition: ndis56common.h:440
LARGE_INTEGER LastTxCompletionTimeStamp
Definition: ndis56common.h:359
tOffloadSettings Offload
Definition: ndis56common.h:470
struct virtqueue * NetReceiveQueue
Definition: ndis56common.h:442
LIST_ENTRY NetReceiveBuffersWaiting
Definition: ndis56common.h:448
PARANDIS_ADAPTER * pContext
Definition: ndis56common.h:499
Definition: ftp_var.h:139
Definition: name.c:39
Definition: dhcpd.h:135
Definition: ps.c:97
volatile u8 * isr
Definition: virtio_pci.h:260
ULONG_PTR addr
Definition: virtio_pci.h:239
VirtIODevice * vdev
Definition: VirtIO.h:44
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
@ Start
Definition: partlist.h:33
#define VIRTIO_CONFIG_S_DRIVER
Definition: virtio_config.h:37
#define SIZE_OF_SINGLE_INDIRECT_DESC
Definition: virtio_config.h:71
#define VIRTIO_CONFIG_S_ACKNOWLEDGE
Definition: virtio_config.h:35
#define VIRTIO_F_ANY_LAYOUT
Definition: virtio_config.h:60
#define VIRTIO_CONFIG_S_FAILED
Definition: virtio_config.h:45
#define VIRTIO_F_VERSION_1
Definition: virtio_config.h:63
#define VIRTIO_CONFIG_S_DRIVER_OK
Definition: virtio_config.h:39
int virtio_get_bar_index(PPCI_COMMON_HEADER pPCIHeader, PHYSICAL_ADDRESS BasePA)
u32 virtio_get_queue_size(struct virtqueue *vq)
NTSTATUS virtio_find_queues(VirtIODevice *vdev, unsigned nvqs, struct virtqueue *vqs[])
NTSTATUS virtio_device_initialize(VirtIODevice *vdev, const VirtIOSystemOps *pSystemOps, void *DeviceContext, bool msix_used)
void virtio_device_shutdown(VirtIODevice *vdev)
void virtio_delete_queues(VirtIODevice *vdev)
void virtio_set_status(VirtIODevice *vdev, u8 status)
void virtio_add_status(VirtIODevice *vdev, u8 status)
void virtio_device_ready(VirtIODevice *vdev)
u8 virtio_read_isr_status(VirtIODevice *vdev)
u64 virtio_get_features(VirtIODevice *dev)
u8 virtio_get_status(VirtIODevice *vdev)
void virtio_device_reset(VirtIODevice *vdev)
void virtio_get_config(VirtIODevice *vdev, unsigned offset, void *buf, unsigned len)
NTSTATUS virtio_set_features(VirtIODevice *vdev, u64 features)
#define VIRTIO_RING_F_INDIRECT_DESC
Definition: virtio_ring.h:39
#define VIRTIO_RING_F_EVENT_IDX
Definition: virtio_ring.h:45
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
#define FORCEINLINE
Definition: wdftypes.h:67
#define PCI_TYPE0_ADDRESSES
Definition: iotypes.h:3500
#define ETH_COMPARE_NETWORK_ADDRESSES(_A, _B, _Result)
Definition: xfilter.h:40
#define ETH_IS_BROADCAST(Address)
Definition: xfilter.h:32
#define ETH_IS_MULTICAST(Address)
Definition: xfilter.h:37
const char * LPCSTR
Definition: xmlstorage.h:183
unsigned char UCHAR
Definition: xmlstorage.h:181