ReactOS  0.4.15-dev-448-gd6c4411
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 
35 static void ReuseReceiveBufferRegular(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor);
36 static 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 /**********************************************************
58 Validates MAC address
59 Valid MAC address is not broadcast, not multicast, not empty
60 if bLocal is set, it must be LOCAL
61 if not, is must be non-local or local
62 Parameters:
63  PUCHAR pcMacAddress - MAC address to validate
64  BOOLEAN bLocal - TRUE, if we validate locally administered address
65 Return 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 
87 typedef struct _tagConfigurationEntry
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 /**********************************************************
195 Gets integer value for specifies in pEntry->Name name
196 Parameters:
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};
207  NdisInitializeString(&name, (PUCHAR)pEntry->Name);
209  &status,
210  &pParam,
211  cfg,
212  &name,
213  ParameterType);
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",
232  __FUNCTION__,
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 /**********************************************************
270 Loads NIC parameters from adapter registry key
271 Parameters:
272  context
273  PUCHAR *ppNewMACAddress - pointer to hold MAC address if configured from host
274 ***********************************************************/
275 static 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);
314  GetConfigurationEntry(cfg, &pConfiguration->VlanId);
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;
383  NdisReadNetworkAddress(&status, &p, &len, cfg);
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);
420  pDest->fTxIPOptions = !!(*from & osbT4IpOptionsChecksum);
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 
441  pDest->fRxTCPv6Checksum = !!(*from & osbT6RxTCPChecksum);
443  pDest->fRxUDPv6Checksum = !!(*from & osbT6RxUDPChecksum);
444  pDest->fRxIPv6Ext = !!(*from & osbT6RxIpExtChecksum);
445 }
446 
447 /**********************************************************
448 Enumerates adapter resources and fills the structure holding them
449 Verifies that IO assigned and has correct size
450 Verifies that interrupt assigned
451 Parameters:
452  PNDIS_RESOURCE_LIST RList - list of resources, received from NDIS
453  tAdapterResources *pResources - structure to fill
454 Return 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  {
477  ULONG type = RList->PartialDescriptors[i].Type;
478  if (type == CmResourceTypePort)
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 
517 static void DumpVirtIOFeatures(PARANDIS_ADAPTER *pContext)
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
556 Parameters:
557 Return value:
558 ***********************************************************/
559 static 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 /**********************************************************
573 Prints out statistics
574 ***********************************************************/
575 static void PrintStatistics(PARANDIS_ADAPTER *pContext)
576 {
577  ULONG64 totalTxFrames =
578  pContext->Statistics.ifHCOutBroadcastPkts +
579  pContext->Statistics.ifHCOutMulticastPkts +
580  pContext->Statistics.ifHCOutUcastPkts;
581  ULONG64 totalRxFrames =
582  pContext->Statistics.ifHCInBroadcastPkts +
583  pContext->Statistics.ifHCInMulticastPkts +
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));
595  pContext->minFreeHardwareBuffers = pContext->nofFreeHardwareBuffers;
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:
626  return NDIS_STATUS_RESOURCES;
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 /**********************************************************
644 Initializes the context structure
645 Major variables, received from NDIS on initialization, must be be set before this call
646 (for ex. pContext->MiniportHandle)
647 
648 If this procedure fails, no need to call
649  ParaNdis_CleanupContext
650 
651 
652 Parameters:
653 Return 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  {
848  pContext->bDoGuestChecksumOnReceive = FALSE;
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 
895  NdisInitializeEvent(&pContext->ResetEvent);
897  return status;
898 }
899 
900 /**********************************************************
901 Free the resources allocated for VirtIO buffer descriptor
902 Parameters:
903  PVOID pParam pIONetDescriptor to free
904  BOOLEAN bRemoveFromList TRUE, if also remove it from list
905 ***********************************************************/
906 static 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 /**********************************************************
921 Free all the buffer descriptors from specified list
922 Parameters:
923  PLIST_ENTRY pListRoot list containing pIONetDescriptor structures
924  PNDIS_SPIN_LOCK pLock lock to protest this list
925 Return value:
926 ***********************************************************/
927 static void FreeDescriptorsFromList(PARANDIS_ADAPTER *pContext, PLIST_ENTRY pListRoot, PNDIS_SPIN_LOCK pLock)
928 {
929  pIONetDescriptor pBufferDescriptor;
930  LIST_ENTRY TempList;
931  InitializeListHead(&TempList);
932  NdisAcquireSpinLock(pLock);
933  while(!IsListEmpty(pListRoot))
934  {
935  pBufferDescriptor = (pIONetDescriptor)RemoveHeadList(pListRoot);
936  InsertTailList(&TempList, &pBufferDescriptor->listEntry);
937  }
938  NdisReleaseSpinLock(pLock);
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"));
971  VirtIONetFreeBufferDescriptor(pContext, p);
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 /**********************************************************
994 Allocates TX buffers according to startup setting (pContext->maxFreeTxDescriptors as got from registry)
995 Buffers are chained in NetFreeSendBuffers
996 Parameters:
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,
1012  pContext->MaxPacketSize.nMaxFullSizeHwTx,
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;
1023  pContext->maxFreeHardwareBuffers = pContext->minFreeHardwareBuffers = pContext->nofFreeHardwareBuffers;
1024  DPrintf(0, ("[%s] available %d Tx descriptors, %d hw buffers",
1026 }
1027 
1028 static BOOLEAN AddRxBufferToQueue(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDescriptor)
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 /**********************************************************
1057 Allocates maximum RX buffers for incoming packets
1058 Buffers are chained in NetReceiveBuffers
1059 Parameters:
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 
1091  virtqueue_kick(pContext->NetReceiveQueue);
1092 
1093  return nRet;
1094 }
1095 
1097 {
1098  struct virtqueue *queues[3];
1099  unsigned nvqs = pContext->bHasControlQueue ? 3 : 2;
1100  NTSTATUS status;
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));
1109  return NTStatusToNdisStatus(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
1122 static void DeleteNetQueues(PARANDIS_ADAPTER *pContext)
1123 {
1124  virtio_delete_queues(&pContext->IODevice);
1125 }
1126 
1127 /**********************************************************
1128 Initializes VirtIO buffering and related stuff:
1129 Allocates RX and TX queues and buffers
1130 Parameters:
1131  context
1132 Return 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 /**********************************************************
1189 Finishes initialization of context structure, calling also version dependent part
1190 If this procedure failed, ParaNdis_CleanupContext must be called
1191 Parameters:
1192  context
1193 Return value:
1194  SUCCESS or some kind of failure
1195 ***********************************************************/
1197 {
1199  DEBUG_ENTRY(0);
1200 
1201  NdisAllocateSpinLock(&pContext->SendLock);
1202 #if !defined(UNIFY_LOCKS)
1203  NdisAllocateSpinLock(&pContext->ReceiveLock);
1204 #endif
1205 
1210 
1212 
1213  if (status == NDIS_STATUS_SUCCESS)
1214  {
1215  status = ParaNdis_VirtIONetInit(pContext);
1216  }
1217 
1218  pContext->Limits.nReusedRxBuffers = pContext->NetMaxReceiveBuffers / 4 + 1;
1219 
1220  if (status == NDIS_STATUS_SUCCESS)
1221  {
1222  JustForCheckClearInterrupt(pContext, "start 3");
1223  pContext->bEnableInterruptHandlingDPC = TRUE;
1225  virtio_device_ready(&pContext->IODevice);
1226  JustForCheckClearInterrupt(pContext, "start 4");
1227  ParaNdis_UpdateDeviceFilters(pContext);
1228  }
1229  else
1230  {
1232  }
1234  return status;
1235 }
1236 
1237 /**********************************************************
1238 Releases VirtIO related resources - queues and buffers
1239 Parameters:
1240  context
1241 Return value:
1242 ***********************************************************/
1243 static void VirtIONetRelease(PARANDIS_ADAPTER *pContext)
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;;
1304  pContext->bEnableInterruptHandlingDPC = FALSE;
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 /**********************************************************
1318 Frees all the resources allocated when the context initialized,
1319  calling also version-dependent part
1320 Parameters:
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 /**********************************************************
1411 System shutdown handler (shutdown, restart, bugcheck)
1412 Parameters:
1413  context
1414 ***********************************************************/
1416 {
1417  DEBUG_ENTRY(0); // this is only for kdbg :)
1419 }
1420 
1421 /**********************************************************
1422 Handles hardware interrupt
1423 Parameters:
1424  context
1425  ULONG knownInterruptSources - bitmask of
1426 Return 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 /**********************************************************
1476 It is called from Rx processing routines in regular mode of operation.
1477 Returns received buffer back to VirtIO queue, inserting it to NetReceiveBuffers.
1478 If needed, signals end of RX pause operation
1479 
1480 Must be called with &pContext->ReceiveLock acquired
1481 
1482 Parameters:
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;
1520  ParaNdis_DebugHistory(pContext, hopInternalReceivePause, NULL, 0, 0, 0);
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 /**********************************************************
1534 It is called from Rx processing routines between power off and power on in non-paused mode (Win8).
1535 Returns received buffer to NetReceiveBuffers.
1536 All the buffers will be placed into Virtio queue during power-on procedure
1537 
1538 Must be called with &pContext->ReceiveLock acquired
1539 
1540 Parameters:
1541  context
1542  void *pDescriptor - pIONetDescriptor to return
1543 ***********************************************************/
1544 static void ReuseReceiveBufferPowerOff(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor)
1545 {
1546  RemoveEntryList(&pBuffersDescriptor->listEntry);
1547  InsertTailList(&pContext->NetReceiveBuffers, &pBuffersDescriptor->listEntry);
1548 }
1549 
1550 /**********************************************************
1551 It is called from Tx processing routines
1552 Gets all the finished buffer from VirtIO TX path and
1553 returns them to NetFreeSendBuffers
1554 
1555 Must be called with &pContext->SendLock acquired
1556 
1557 Parameters:
1558  context
1559 Return 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 
1595 static 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 /*********************************************************
1616 Called with from ProcessTx routine with TxLock held
1617 Uses 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  {
1672  result = ParaNdis_DoCopyPacketData(pContext, Params);
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  {
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 /**********************************************************
1848 It is called from Tx processing routines
1849 Prepares the VirtIO buffer and copies to it the data from provided packet
1850 
1851 Must be called with &pContext->SendLock acquired
1852 
1853 Parameters:
1854  context
1855  tPacketType packet specific type is NDIS dependent
1856  tCopyPacketDataFunction PacketCopier procedure for NDIS-specific type of packet
1857 Return 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?
1892  if ((flags & (pcrTcpChecksum | pcrUdpChecksum | pcrIpChecksum)) != 0)
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;
1934  if (flags & pcrIpChecksum) csFlags |= pcrIpChecksum | pcrFixIPChecksum;
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 
2064 void
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 /**********************************************************
2088 Manages RX path, calling NDIS-specific procedure for packet indication
2089 Parameters:
2090  context
2091 ***********************************************************/
2092 static 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  {
2218  virtqueue_disable_cb(_vq);
2219  res = false;
2220  }
2221 
2222  ParaNdis_DebugHistory(SyncContext->pContext, hopDPC, (PVOID)SyncContext->Parameter, 0x20, res, 0);
2223  return !res;
2224 }
2225 /**********************************************************
2226 DPC implementation, common for both NDIS
2227 Parameters:
2228  context
2229 ***********************************************************/
2230 ULONG 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  {
2250  ParaNdis_ReportLinkStatus(pContext, FALSE);
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 /**********************************************************
2332 Periodically called procedure, checking dpc activity
2333 If DPC are not running, it does exactly the same that the DPC
2334 Parameters:
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 /**********************************************************
2417 Common implementation of periodic poll
2418 Parameters:
2419  context
2420 Return:
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 /**********************************************************
2436 Common handler of multicast address configuration
2437 Parameters:
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
2442 Return value:
2443  SUCCESS or kind of failure
2444 ***********************************************************/
2446  PARANDIS_ADAPTER *pContext,
2447  PVOID Buffer,
2448  ULONG BufferSize,
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  {
2462  *pBytesNeeded = (length / ETH_LENGTH_OF_ADDRESS) * ETH_LENGTH_OF_ADDRESS;
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 /**********************************************************
2478 Callable from synchronized routine or interrupt handler
2479 to enable or disable Rx and/or Tx interrupt generation
2480 Parameters:
2481  context
2482  interruptSource - isReceive, isTransmit
2483  b - 1/0 enable/disable
2484 ***********************************************************/
2486 {
2487  if (interruptSource & isTransmit)
2488  virtqueue_enable_cb(pContext->NetSendQueue);
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 /**********************************************************
2504 Common handler of PnP events
2505 Parameters:
2506 Return 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));
2531  if (pEvent == NdisDevicePnPEventSurpriseRemoved)
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);
2593  *(virtio_net_ctrl_ack *)(pBase + offset) = VIRTIO_NET_ERR;
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  {
2654  struct virtio_net_ctrl_mac header;
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 
2663 static 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 
2754  ParaNdis_UpdateDeviceFilters(pContext);
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  }
2786  virtqueue_kick(pContext->NetReceiveQueue);
2788  pContext->bEnableInterruptHandlingDPC = TRUE;
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 
2799  ParaNdis_ReportLinkStatus(pContext, TRUE);
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 
2810  ParaNdis_IndicateConnect(pContext, FALSE, FALSE);
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);
2839  virtqueue_shutdown(pContext->NetSendQueue);
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 {
2879  tOffloadSettingsFlags f = pContext->Offload.flags;
2880  tChecksumCheckResult res, resIp;
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
3002  tChecksumCheckResult diff;
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 }
VirtIOSystemOps ParaNdisSystemOps
#define ETH_IS_LOCALLY_ADMINISTERED(Address)
Definition: ethernetutils.h:35
static void JustForCheckClearInterrupt(PARANDIS_ADAPTER *pContext, const char *Label)
signed char * PCHAR
Definition: retypes.h:7
LIST_ENTRY listEntry
Definition: ndis56common.h:336
VOID ParaNdis_UpdateDeviceFilters(PARANDIS_ADAPTER *pContext)
#define PARANDIS_UNLIMITED_PACKETS_TO_INDICATE
Definition: ndis56common.h:128
NDIS_OFFLOAD_PARAMETERS InitialOffloadParameters
Definition: ndis56common.h:471
#define ETH_IS_BROADCAST(Address)
Definition: xfilter.h:32
void virtio_device_ready(VirtIODevice *vdev)
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@379::@381 Port
tSendReceiveState ReceiveState
Definition: ndis56common.h:435
struct _tagConfigurationEntries tConfigurationEntries
#define DEBUG_EXIT_STATUS(level, status)
Definition: kdebugprint.h:50
#define PCI_TYPE0_ADDRESSES
Definition: iotypes.h:3144
VOID ParaNdis_PacketMapper(PARANDIS_ADAPTER *pContext, tPacketType packet, PVOID Reference, struct VirtIOBufferDescriptor *buffers, pIONetDescriptor pDesc, tMapperResult *pMapperResult)
GLint level
Definition: gl.h:1546
NDIS_SPIN_LOCK ReceiveLock
Definition: ndis56common.h:412
USHORT usBuffersMapped
Definition: ndis56common.h:687
void virtio_device_shutdown(VirtIODevice *vdev)
void ParaNdis_CallOnBugCheck(PARANDIS_ADAPTER *pContext)
#define TRUE
Definition: types.h:120
#define ETH_COMPARE_NETWORK_ADDRESSES(_A, _B, _Result)
Definition: xfilter.h:38
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID ParaNdis_OnShutdown(PARANDIS_ADAPTER *pContext)
VOID EXPORT NdisAllocateSpinLock(IN PNDIS_SPIN_LOCK SpinLock)
Definition: control.c:152
static VOID ParaNdis_DeviceFiltersUpdateAddresses(PARANDIS_ADAPTER *pContext)
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
void ParaNdis_UnbindBufferFromPacket(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDesc)
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@379::@384 Memory
static void virtqueue_kick_always(struct virtqueue *vq)
Definition: VirtIO.h:80
#define VIRTIO_NET_CTRL_MAC
u8 virtio_get_status(VirtIODevice *vdev)
static NDIS_STATUS FindNetQueues(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_F_HOST_TSO6
Definition: ndis56common.h:105
UCHAR packet[_PAGE_SIZE]
Definition: serial.c:53
#define VIRTIO_F_ANY_LAYOUT
Definition: virtio_config.h:60
tConfigurationEntry UseSwTxChecksum
int virtio_get_bar_index(PPCI_COMMON_HEADER pPCIHeader, PHYSICAL_ADDRESS BasePA)
NDIS_DEVICE_POWER_STATE powerState
Definition: ndis56common.h:389
tAdapterResources AdapterResources
Definition: ndis56common.h:351
static const tConfigurationEntries defaultConfiguration
#define VIRTIO_NET_CTRL_RX_MODE
VOID ParaNdis_Suspend(PARANDIS_ADAPTER *pContext)
Definition: ftp_var.h:139
enum _tag_eInspectedPacketType eInspectedPacketType
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
tConfigurationEntry VlanId
static BOOLEAN GetAdapterResources(NDIS_HANDLE MiniportHandle, PNDIS_RESOURCE_LIST RList, tAdapterResources *pResources)
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
tConfigurationEntry TxCapacity
tConfigurationEntry stdTcpcsV6
VOID EXPORT NdisReleaseSpinLock(IN PNDIS_SPIN_LOCK SpinLock)
Definition: control.c:239
unsigned char * PUCHAR
Definition: retypes.h:3
tConfigurationEntry PrioritySupport
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@379::@382 Interrupt
static void VirtIODeviceEnableGuestFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
Definition: ndis56common.h:521
LIST_ENTRY NetReceiveBuffersWaiting
Definition: ndis56common.h:448
#define VIRTIO_NET_F_STATUS
Definition: ndis56common.h:109
ULONG64 ifHCOutMulticastPkts
Definition: ndis56common.h:278
static void VirtIONetFreeBufferDescriptor(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDescriptor)
LONG NTSTATUS
Definition: precomp.h:26
#define DEBUG_ENTRY(level)
Definition: kdebugprint.h:49
VOID ParaNdis_IndicateReceivedBatch(PARANDIS_ADAPTER *pContext, tPacketIndicationType *pBatch, ULONG nofPackets)
struct VirtIOBufferDescriptor * sgTxGatherTable
Definition: ndis56common.h:467
ULONG64 ifHCInBroadcastPkts
Definition: ndis56common.h:271
tConfigurationEntry debugLevel
#define RtlOffsetToPointer(Base, Offset)
Definition: ndis56common.h:50
union _NDIS_CONFIGURATION_PARAMETER::@2062 ParameterData
static VOID SetSingleVlanFilter(PARANDIS_ADAPTER *pContext, ULONG vlanId, BOOLEAN bOn, int levelIfOK)
GLintptr offset
Definition: glext.h:5920
tOurCounters Limits
Definition: ndis56common.h:433
static void DumpVirtIOFeatures(PARANDIS_ADAPTER *pContext)
BOOLEAN ParaNdis_ProcessTx(PARANDIS_ADAPTER *pContext, BOOLEAN IsDpc, BOOLEAN IsInterrupt)
BOOLEAN bEnableInterruptChecking
Definition: ndis56common.h:365
tTcpIpPacketParsingResult ParaNdis_CheckSumVerify(PVOID buffer, ULONG size, ULONG flags, LPCSTR caller)
Definition: sw-offload.c:565
GLdouble n
Definition: glext.h:7729
ULONG64 ifHCOutUcastPkts
Definition: ndis56common.h:276
static ULONG FORCEINLINE QueryTcpHeaderOffset(PVOID packetData, ULONG ipHeaderOffset, ULONG ipPacketLength)
VOID EXPORT NdisMUnmapIoSpace(IN NDIS_HANDLE MiniportAdapterHandle, IN PVOID VirtualAddress, IN UINT Length)
Definition: io.c:1139
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
tPacketHolderType pHolder
Definition: ndis56common.h:339
tCompletePhysicalAddress ControlData
Definition: ndis56common.h:441
volatile u8 * isr
Definition: virtio_pci.h:260
ULONGLONG ullGuestFeatures
Definition: ndis56common.h:357
void virtio_add_status(VirtIODevice *vdev, u8 status)
#define ETH_HAS_PRIO_HEADER(Address)
Definition: ethernetutils.h:41
char * cmd
Definition: vfdcmd.c:85
enum _NDIS_DEVICE_PNP_EVENT NDIS_DEVICE_PNP_EVENT
tConfigurationEntry OffloadTxLSO
VOID ParaNdis_CleanupContext(PARANDIS_ADAPTER *pContext)
#define ETH_PRIORITY_HEADER_SIZE
Definition: ethernetutils.h:56
static HANDLE proc()
Definition: pdb.c:32
NTSTATUS virtio_find_queues(VirtIODevice *vdev, unsigned nvqs, struct virtqueue *vqs[])
tBusResource SharedMemoryRanges[MAX_NUM_OF_QUEUES]
Definition: ndis56common.h:352
LIST_ENTRY NetReceiveBuffers
Definition: ndis56common.h:445
#define InsertTailList(ListHead, Entry)
#define VIRTIO_NET_F_GUEST_TSO4
Definition: ndis56common.h:100
#define CM_RESOURCE_INTERRUPT_MESSAGE
Definition: cmtypes.h:145
#define ETH_ALEN
Definition: dhcpd.h:50
#define VIRTIO_NET_CTRL_RX_MODE_NOUNI
tConfigurationEntry connectTimer
#define VIRTIO_NET_F_CTRL_VLAN
Definition: ndis56common.h:112
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID ParaNdis_FreePhysicalMemory(PARANDIS_ADAPTER *pContext, tCompletePhysicalAddress *pAddresses)
#define PARANDIS_STORE_LAST_INTERRUPT_TIMESTAMP(p)
Definition: DebugData.h:107
BOOLEAN bIODeviceInitialized
Definition: ndis56common.h:355
#define CmResourceTypePort
Definition: hwresource.cpp:123
tConfigurationEntry OffloadGuestCS
#define VIRTIO_NET_CTRL_VLAN
tConfigurationEntry BatchReceive
NDIS_PHYSICAL_ADDRESS BasePA
Definition: ndis56common.h:161
#define TCP_CHECKSUM_OFFSET
static VOID ParaNdis_DeviceFiltersUpdateRxMode(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_CTRL_VLAN_DEL
tConfigurationEntry OffloadRxCS
BOOLEAN bEnableInterruptHandlingDPC
Definition: ndis56common.h:364
struct _tagPARANDIS_ADAPTER::@994 extraStatistics
static BOOLEAN RestartQueueSynchronously(tSynchronizedContext *SyncContext)
int NDIS_STATUS
Definition: ntddndis.h:471
tOffloadSettingsFlags flags
Definition: ndis56common.h:237
NDIS_STATISTICS_INFO Statistics
Definition: ndis56common.h:420
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define VIRTIO_NET_F_CTRL_RX_EXTRA
Definition: ndis56common.h:113
tConfigurationEntry dpcChecker
static void DisableLSOv6Permanently(PARANDIS_ADAPTER *pContext, LPCSTR procname, LPCSTR reason)
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:337
tConfigurationEntry RxCapacity
void ParaNdis_ResetOffloadSettings(PARANDIS_ADAPTER *pContext, tOffloadSettingsFlags *pDest, PULONG from)
#define VIRTIO_NET_F_GUEST_TSO6
Definition: ndis56common.h:101
BOOLEAN ParaNdis_BindBufferToPacket(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDesc)
void ParaNdis_ReportLinkStatus(PARANDIS_ADAPTER *pContext, BOOLEAN bForce)
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
#define UDP_CHECKSUM_OFFSET
#define NDIS_STATUS_INVALID_DEVICE_REQUEST
Definition: ndis.h:510
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
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
ULONG ParaNdis_DPCWorkBody(PARANDIS_ADAPTER *pContext, ULONG ulMaxPacketsToIndicate)
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
Definition: lan.h:33
static VOID SetAllVlanFilters(PARANDIS_ADAPTER *pContext, BOOLEAN bOn)
static BOOLEAN FORCEINLINE IsPrioritySupported(PARANDIS_ADAPTER *pContext)
Definition: ndis56common.h:547
static BOOLEAN AddRxBufferToQueue(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBufferDescriptor)
tConfigurationEntry ScatterGather
_Must_inspect_result_ _Out_ PNDIS_STATUS _Out_ PNDIS_CONFIGURATION_PARAMETER _In_ NDIS_HANDLE _In_ PNDIS_STRING _In_ NDIS_PARAMETER_TYPE ParameterType
Definition: ndis.h:4413
long LONG
Definition: pedump.c:60
static void ParaNdis_ResetVirtIONetDevice(PARANDIS_ADAPTER *pContext)
static void PrintStatistics(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_F_GUEST_CSUM
Definition: ndis56common.h:97
VOID ParaNdis_OnTransmitBufferReleased(PARANDIS_ADAPTER *pContext, IONetDescriptor *pDesc)
tConfigurationEntry stdLsoV1
tConfigurationEntry stdIpcsV4
tConfigurationEntry isLogEnabled
ULONG64 ifHCInMulticastOctets
Definition: ndis56common.h:270
u8 virtio_read_isr_status(VirtIODevice *vdev)
#define VIRTIO_CONFIG_S_DRIVER
Definition: virtio_config.h:37
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:573
PVOID ParaNdis_AllocateMemory(PARANDIS_ADAPTER *pContext, ULONG ulRequiredSize)
struct NameRec_ * Name
Definition: cdprocs.h:464
#define DPrintf(Level, Fmt)
Definition: kdebugprint.h:61
USHORT usBufferSpaceUsed
Definition: ndis56common.h:688
#define ETH_MIN_PACKET_SIZE
Definition: ethernetutils.h:54
ULONG64 ifHCOutBroadcastOctets
Definition: ndis56common.h:281
tCompletePhysicalAddress HeaderInfo
Definition: ndis56common.h:337
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define NDIS_STATUS_INVALID_LENGTH
Definition: ndis.h:485
NDIS_DEVICE_PNP_EVENT PnpEvents[16]
Definition: ndis56common.h:469
VOID EXPORT NdisFreeSpinLock(IN PNDIS_SPIN_LOCK SpinLock)
Definition: control.c:204
tConfigurationEntry ConnectRate
VOID ParaNdis_FinalizeCleanup(PARANDIS_ADAPTER *pContext)
#define FORCEINLINE
Definition: ntbasedef.h:221
static BOOLEAN FORCEINLINE IsVlanSupported(PARANDIS_ADAPTER *pContext)
Definition: ndis56common.h:542
static __inline BOOLEAN ParaNDIS_IsQueueInterruptEnabled(struct virtqueue *_vq)
Definition: ndis56common.h:601
ULONG64 ifHCInMulticastPkts
Definition: ndis56common.h:269
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
UCHAR CurrentMacAddress[ETH_LENGTH_OF_ADDRESS]
Definition: ndis56common.h:402
#define VIRTIO_NET_CTRL_RX_MODE_PROMISC
#define VIRTIO_NET_F_HOST_TSO4
Definition: ndis56common.h:104
Definition: bufpool.h:45
#define MAX_RX_LOOPS
Definition: ndis56common.h:90
#define VIRTIO_NET_F_MAC
Definition: ndis56common.h:98
NDIS_STATUS ParaNdis_SetMulticastList(PARANDIS_ADAPTER *pContext, PVOID Buffer, ULONG BufferSize, PUINT pBytesRead, PUINT pBytesNeeded)
const char * LPCSTR
Definition: xmlstorage.h:183
BOOLEAN bPortSpace
Definition: ndis56common.h:164
#define NDIS_STATUS_MULTICAST_FULL
Definition: ndis.h:473
#define NDIS_PACKET_TYPE_ALL_MULTICAST
Definition: ndis.h:665
VOID ParaNdis_VirtIOEnableIrqSynchronized(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
#define VIRTIO_NET_S_LINK_UP
Definition: ndis56common.h:115
#define VIRTIO_NET_F_CTRL_RX
Definition: ndis56common.h:111
#define b
Definition: ke_i.h:79
VOID(* ONPAUSECOMPLETEPROC)(VOID *)
Definition: ndis56common.h:150
static NDIS_STATUS ParaNdis_VirtIONetInit(PARANDIS_ADAPTER *pContext)
GLuint GLfloat * val
Definition: glext.h:7180
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
VOID EXPORT NdisCloseConfiguration(IN NDIS_HANDLE ConfigurationHandle)
Definition: config.c:136
tConfigurationEntry NumberOfHandledRXPackersInDPC
#define VIRTIO_CONFIG_S_ACKNOWLEDGE
Definition: virtio_config.h:35
struct _tagConfigurationEntry tConfigurationEntry
tConfigurationEntry stdTcpcsV4
static void DisableLSOv4Permanently(PARANDIS_ADAPTER *pContext, LPCSTR procname, LPCSTR reason)
Definition: dhcpd.h:135
#define VIRTIO_RING_F_EVENT_IDX
Definition: virtio_ring.h:45
#define VIRTIO_NET_F_GUEST_ECN
Definition: ndis56common.h:102
KSPIN_LOCK SpinLock
Definition: ndis.h:330
#define VIRTIO_NET_HDR_F_NEEDS_CSUM
#define STATUS_NOT_FOUND
Definition: shellext.h:72
MmuTrapHandler callback[0x30]
Definition: mmuobject.c:44
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
tConfigurationEntry PacketFiltering
static LPSTR pName
Definition: security.c:75
void virtio_device_reset(VirtIODevice *vdev)
tConfigurationEntry UseMergeableBuffers
#define VIRTIO_NET_F_GSO
Definition: ndis56common.h:99
struct _tagvirtio_net_hdr_ext virtio_net_hdr_ext
static void ReadNicConfiguration(PARANDIS_ADAPTER *pContext, PUCHAR *ppNewMACAddress)
if(!(yy_init))
Definition: macro.lex.yy.c:714
struct _ETH_HEADER ETH_HEADER
static void PreventDPCServicing(PARANDIS_ADAPTER *pContext)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
tReuseReceiveBufferProc ReuseBufferProc
Definition: ndis56common.h:438
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
BOOLEAN bDoInterruptRecovery
Definition: ndis56common.h:366
VOID ParaNdis_Resume(PARANDIS_ADAPTER *pContext)
struct _tagChecksumCheckResult::@991::@993 flags
VOID EXPORT NdisAcquireSpinLock(IN PNDIS_SPIN_LOCK SpinLock)
Definition: control.c:135
#define ETH_IS_EMPTY(Address)
Definition: ethernetutils.h:38
uint64_t ULONGLONG
Definition: typedefs.h:66
ULONGLONG ulFormalLinkSpeed
Definition: ndis56common.h:396
BOOLEAN ParaNdis_OnLegacyInterrupt(PARANDIS_ADAPTER *pContext, OUT BOOLEAN *pRunDpc)
void(* tReuseReceiveBufferProc)(void *pContext, pIONetDescriptor pDescriptor)
Definition: ndis56common.h:344
#define VIRTIO_NET_HDR_F_DATA_VALID
static void ReuseReceiveBufferPowerOff(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor)
NDIS_HANDLE MiniportHandle
Definition: ndis56common.h:349
BOOLEAN bFastSuspendInProcess
Definition: ndis56common.h:384
tConfigurationEntry MTU
NDIS_STATUS ParaNdis_PowerOn(PARANDIS_ADAPTER *pContext)
#define BufferSize
Definition: classpnp.h:419
void ParaNdis_IndicateConnect(PARANDIS_ADAPTER *pContext, BOOLEAN bConnected, BOOLEAN bForce)
enum _NDIS_PARAMETER_TYPE NDIS_PARAMETER_TYPE
GLuint address
Definition: glext.h:9393
BOOL bConnected
Definition: fdebug.c:27
static void GetConfigurationEntry(NDIS_HANDLE cfg, tConfigurationEntry *pEntry)
VOID EXPORT NdisInitializeString(IN OUT PNDIS_STRING DestinationString, IN PUCHAR SourceString)
Definition: string.c:101
UCHAR u8
Definition: btrfs.h:12
#define VIRTIO_NET_F_GUEST_UFO
Definition: ndis56common.h:103
#define NDIS_PACKET_TYPE_MULTICAST
Definition: ndis.h:664
NDIS_HANDLE ParaNdis_OpenNICConfiguration(PARANDIS_ADAPTER *pContext)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Definition: partlist.h:33
#define NDIS_STATUS_ADAPTER_NOT_FOUND
Definition: ndis.h:470
GLbitfield flags
Definition: glext.h:7161
tConfigurationEntry stdUdpcsV4
NTSTATUS virtio_device_initialize(VirtIODevice *vdev, const VirtIOSystemOps *pSystemOps, void *DeviceContext, bool msix_used)
NDIS_STATUS NTAPI ParaNdis_FinishSpecificInitialization(PARANDIS_ADAPTER *pContext)
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
#define VIRTIO_NET_CTRL_MAC_TABLE_SET
static void FreeDescriptorsFromList(PARANDIS_ADAPTER *pContext, PLIST_ENTRY pListRoot, PNDIS_SPIN_LOCK pLock)
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
unsigned __int64 ULONG64
Definition: imports.h:198
struct virtqueue * NetControlQueue
Definition: ndis56common.h:440
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID EXPORT NdisReadNetworkAddress(OUT PNDIS_STATUS Status, OUT PVOID *NetworkAddress, OUT PUINT NetworkAddressLength, IN NDIS_HANDLE ConfigurationHandle)
Definition: config.c:740
void virtio_get_config(VirtIODevice *vdev, unsigned offset, void *buf, unsigned len)
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
static void PrepareTransmitBuffers(PARANDIS_ADAPTER *pContext)
UINT ParaNdis_VirtIONetReleaseTransmitBuffers(PARANDIS_ADAPTER *pContext)
GLenum const GLvoid * addr
Definition: glext.h:9621
static void virtqueue_shutdown(struct virtqueue *vq)
Definition: VirtIO.h:120
static eInspectedPacketType QueryPacketType(PVOID data)
int bDebugPrint
#define InterlockedDecrement
Definition: armddk.h:52
NDIS_STATUS ParaNdis_FinishInitialization(PARANDIS_ADAPTER *pContext)
LIST_ENTRY NetFreeSendBuffers
Definition: ndis56common.h:452
void ParaNdis_PadPacketReceived(PVOID pDataBuffer, PULONG pLength)
ULONG64 ifHCInBroadcastOctets
Definition: ndis56common.h:272
#define VIRTIO_NET_F_CTRL_VQ
Definition: ndis56common.h:110
UCHAR MulticastList[ETH_LENGTH_OF_ADDRESS *PARANDIS_MULTICAST_LIST_SIZE]
Definition: ndis56common.h:332
ULONG LowPart
Definition: typedefs.h:105
VOID EXPORT NdisGetCurrentSystemTime(IN OUT PLARGE_INTEGER pSystemTime)
Definition: time.c:51
GLenum GLsizei len
Definition: glext.h:6722
LARGE_INTEGER LastTxCompletionTimeStamp
Definition: ndis56common.h:359
#define InterlockedOr
Definition: interlocked.h:224
static bool VirtIODeviceGetHostFeature(PARANDIS_ADAPTER *pContext, unsigned uFeature)
Definition: ndis56common.h:514
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@379 u
static void DisableBothLSOPermanently(PARANDIS_ADAPTER *pContext, LPCSTR procname, LPCSTR reason)
tConfigurationEntry OffloadTxChecksum
Definition: typedefs.h:118
void virtqueue_kick(struct virtqueue *vq)
static bool virtqueue_enable_cb(struct virtqueue *vq)
Definition: VirtIO.h:95
#define VIRTIO_NET_CTRL_RX_MODE_NOBCAST
ULONG64 ifHCInUcastOctets
Definition: ndis56common.h:268
UINT uNumberOfHandledRXPacketsInDPC
Definition: ndis56common.h:388
#define NDIS_STATUS_RESOURCE_CONFLICT
Definition: ndis.h:495
static void FORCEINLINE ParaNdis_DebugHistory(PARANDIS_ADAPTER *pContext, eHistoryLogOperation op, PVOID pParam1, ULONG lParam2, ULONG lParam3, ULONG lParam4)
Definition: ndis56common.h:647
#define InterlockedExchange
Definition: armddk.h:54
static void VirtIONetRelease(PARANDIS_ADAPTER *pContext)
static void ReuseReceiveBufferRegular(PARANDIS_ADAPTER *pContext, pIONetDescriptor pBuffersDescriptor)
BOOLEAN bLinkDetectSupported
Definition: ndis56common.h:371
struct virtqueue * NetReceiveQueue
Definition: ndis56common.h:442
BOOLEAN ParaNdis_InitialAllocatePhysicalMemory(PARANDIS_ADAPTER *pContext, tCompletePhysicalAddress *pAddresses)
tCopyPacketResult ParaNdis_DoCopyPacketData(PARANDIS_ADAPTER *pContext, tTxOperationParameters *pParams)
#define MAX_NUM_OF_QUEUES
Definition: ndis56common.h:93
static pIONetDescriptor AllocatePairOfBuffersOnInit(PARANDIS_ADAPTER *pContext, ULONG size1, ULONG size2, BOOLEAN bForTx)
int nDebugLevel
tChecksumCheckResult ParaNdis_CheckRxChecksum(PARANDIS_ADAPTER *pContext, ULONG virtioFlags, PVOID pRxPacket, ULONG len)
static BOOLEAN SendControlMessage(PARANDIS_ADAPTER *pContext, UCHAR cls, UCHAR cmd, PVOID buffer1, ULONG size1, PVOID buffer2, ULONG size2, int levelIfOK)
LIST_ENTRY NetSendBuffersInUse
Definition: ndis56common.h:450
tOffloadSettings Offload
Definition: ndis56common.h:470
ULONG EXPORT NdisReadPciSlotInformation(IN NDIS_HANDLE NdisAdapterHandle, IN ULONG SlotNumber, IN ULONG Offset, IN PVOID Buffer, IN ULONG Length)
Definition: hardware.c:180
#define VIRTIO_NET_ERR
tOurCounters Counters
Definition: ndis56common.h:432
VOID ParaNdis_OnPnPEvent(PARANDIS_ADAPTER *pContext, NDIS_DEVICE_PNP_EVENT pEvent, PVOID pInfo, ULONG ulSize)
static ULONG ShallPassPacket(PARANDIS_ADAPTER *pContext, PVOID address, UINT len, eInspectedPacketType *pType)
ONPAUSECOMPLETEPROC ReceivePauseCompletionProc
Definition: ndis56common.h:437
static int PrepareReceiveBuffers(PARANDIS_ADAPTER *pContext)
ULONG64 ifHCOutBroadcastPkts
Definition: ndis56common.h:280
static void WriteVirtIODeviceByte(ULONG_PTR ulRegister, u8 bValue)
void ParaNdis_RestoreDeviceConfigurationAfterReset(PARANDIS_ADAPTER *pContext)
#define InterlockedIncrement
Definition: armddk.h:53
VOID EXPORT NdisMSleep(IN ULONG MicrosecondsToSleep)
Definition: miniport.c:2928
unsigned short USHORT
Definition: pedump.c:61
#define ETH_IS_MULTICAST(Address)
Definition: xfilter.h:35
BOOLEAN ParaNdis_CheckForHang(PARANDIS_ADAPTER *pContext)
VOID ParaNdis_DeviceFiltersUpdateVlanId(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_F_MRG_RXBUF
Definition: ndis56common.h:108
BOOLEAN bDoGuestChecksumOnReceive
Definition: ndis56common.h:373
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI
tConfigurationEntry LogStatistics
void virtio_delete_queues(VirtIODevice *vdev)
tConfigurationEntry PriorityVlanTagging
unsigned int * PULONG
Definition: retypes.h:1
#define ETH_LENGTH_OF_ADDRESS
Definition: efilter.h:16
#define min(a, b)
Definition: monoChain.cc:55
ULONGLONG ullHostFeatures
Definition: ndis56common.h:356
unsigned int UINT
Definition: ndis.h:50
static BOOLEAN CheckRunningDpc(PARANDIS_ADAPTER *pContext)
#define NdisFreeString(_s)
Definition: ndis.h:4076
static bool virtqueue_enable_cb_delayed(struct virtqueue *vq)
Definition: VirtIO.h:100
#define NDIS_PACKET_TYPE_PROMISCUOUS
Definition: ndis.h:668
VOID EXPORT NdisMDeregisterIoPortRange(IN NDIS_HANDLE MiniportAdapterHandle, IN UINT InitialPort, IN UINT NumberOfPorts, IN PVOID PortOffset)
Definition: io.c:1093
u8 virtio_net_ctrl_ack
#define CmResourceTypeInterrupt
Definition: hwresource.cpp:124
void virtio_set_status(VirtIODevice *vdev, u8 status)
static __inline struct virtqueue * ParaNdis_GetQueueForInterrupt(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
Definition: ndis56common.h:590
#define MAKECASE(x)
tConfigurationEntry stdLsoV2ip6
LPCConfig pConfiguration
Definition: config.cpp:18
#define MAX_VLAN_ID
PHYSICAL_ADDRESS Physical
Definition: ndis56common.h:322
tConfigurationEntry stdUdpcsV6
#define NdisZeroMemory(Destination, Length)
Definition: ndis.h:3926
VirtIODevice IODevice
Definition: ndis56common.h:354
tMaxPacketSize MaxPacketSize
Definition: ndis56common.h:398
#define ETH_HEADER_SIZE
Definition: ethernetutils.h:53
NTSTATUS virtio_set_features(VirtIODevice *vdev, u64 features)
#define SIZE_OF_SINGLE_INDIRECT_DESC
Definition: virtio_config.h:71
#define PARANDIS_MAX_LSO_SIZE
Definition: ndis56common.h:126
tCopyPacketResult ParaNdis_PacketCopier(tPacketType packet, PVOID dest, ULONG maxSize, PVOID refValue, BOOLEAN bPreview)
PARANDIS_ADAPTER * pContext
Definition: ndis56common.h:499
Definition: name.c:38
NDIS_STATUS ParaNdis_InitializeContext(PARANDIS_ADAPTER *pContext, PNDIS_RESOURCE_LIST pResourceList)
#define OUT
Definition: typedefs.h:40
VOID ParaNdis_PowerOff(PARANDIS_ADAPTER *pContext)
GLuint res
Definition: glext.h:9613
VirtIODevice * vdev
Definition: VirtIO.h:44
void FORCEINLINE DebugDumpPacket(LPCSTR prefix, PVOID header, int level)
static void VirtIODeviceRemoveStatus(VirtIODevice *vdev, u8 status)
u32 virtio_get_queue_size(struct virtqueue *vq)
static void DeleteNetQueues(PARANDIS_ADAPTER *pContext)
#define VIRTIO_NET_F_CSUM
Definition: ndis56common.h:96
#define NDIS_STATUS_RESOURCES
Definition: ndis.h:466
unsigned int ULONG
Definition: retypes.h:1
tCopyPacketResult ParaNdis_DoSubmitPacket(PARANDIS_ADAPTER *pContext, tTxOperationParameters *Params)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
PWCHAR Label
Definition: format.c:70
#define VIRTIO_CONFIG_S_DRIVER_OK
Definition: virtio_config.h:39
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:582
static NDIS_STATUS FinalizeFeatures(PARANDIS_ADAPTER *pContext)
tConfigurationEntry InterruptRecovery
PHYSICAL_ADDRESS physAddr
Definition: VirtIO.h:9
#define VIRTIO_NET_CTRL_VLAN_ADD
struct tag_virtio_net_ctrl_hdr virtio_net_ctrl_hdr
BOOLEAN ParaNdis_SynchronizeWithInterrupt(PARANDIS_ADAPTER *pContext, ULONG messageId, tSynchronizedProcedure procedure, PVOID parameter)
#define VIRTIO_CONFIG_S_FAILED
Definition: virtio_config.h:45
static void * virtqueue_get_buf(struct virtqueue *vq, unsigned int *len)
Definition: VirtIO.h:85
#define VIRTIO_NET_INVALID_INTERRUPT_STATUS
Definition: ndis56common.h:117
BOOLEAN ParaNdis_OnQueuedInterrupt(PARANDIS_ADAPTER *pContext, OUT BOOLEAN *pRunDpc, ULONG knownInterruptSources)
struct virtqueue * NetSendQueue
Definition: ndis56common.h:443
VOID EXPORT NdisInitializeEvent(IN PNDIS_EVENT Event)
Definition: control.c:221
GLfloat GLfloat p
Definition: glext.h:8902
BOOLEAN bDoHwPacketFiltering
Definition: ndis56common.h:368
tMulticastData MulticastData
Definition: ndis56common.h:387
#define CmResourceTypeMemory
Definition: hwresource.cpp:125
CardRegion * from
Definition: spigame.cpp:19
UCHAR PermanentMacAddress[ETH_LENGTH_OF_ADDRESS]
Definition: ndis56common.h:401
#define VIRTIO_RING_F_INDIRECT_DESC
Definition: virtio_ring.h:39
VOID ParaNdis_SetPowerState(PARANDIS_ADAPTER *pContext, NDIS_DEVICE_POWER_STATE newState)
#define VIRTIO_F_VERSION_1
Definition: virtio_config.h:63
return STATUS_SUCCESS
Definition: btrfs.c:3014
ULONG_PTR addr
Definition: virtio_pci.h:239
VOID ParaNdis_VirtIODisableIrqSynchronized(PARANDIS_ADAPTER *pContext, ULONG interruptSource)
tPacketIndicationType ParaNdis_IndicateReceivedPacket(PARANDIS_ADAPTER *pContext, PVOID dataBuffer, PULONG pLength, BOOLEAN bPrepareOnly, pIONetDescriptor pBufferDesc)
tConfigurationEntry Indirect
USHORT u16
Definition: btrfs.h:13
#define NdisMoveMemory(Destination, Source, Length)
Definition: ndis.h:3896
ULONG64 ifHCOutUcastOctets
Definition: ndis56common.h:277
#define __FUNCTION__
Definition: types.h:112
GLuint64EXT * result
Definition: glext.h:11304
static void virtqueue_disable_cb(struct virtqueue *vq)
Definition: VirtIO.h:90
tConfigurationEntry isPromiscuous
static SERVICE_STATUS status
Definition: service.c:31
tConfigurationEntry stdLsoV2ip4
#define VIRTIO_NET_OK
tCompletePhysicalAddress DataInfo
Definition: ndis56common.h:338
#define VIRTIO_NET_F_HOST_ECN
Definition: ndis56common.h:106
static UINT ParaNdis_ProcessRxPath(PARANDIS_ADAPTER *pContext, ULONG ulMaxPacketsToIndicate)
#define VIRTIO_NET_CTRL_RX_MODE_NOMULTI
NDIS_SPIN_LOCK SendLock
Definition: ndis56common.h:411
tTcpIpPacketParsingResult ParaNdis_ReviewIPPacket(PVOID buffer, ULONG size, LPCSTR caller)
Definition: sw-offload.c:614
#define NDIS_STATUS_FAILURE
Definition: ndis.h:465
u64 virtio_get_features(VirtIODevice *dev)
tConfigurationEntry IPPacketsCheck
VOID EXPORT NdisFreeMemory(IN PVOID VirtualAddress, IN UINT Length, IN UINT MemoryFlags)
Definition: memory.c:110
unsigned int * PUINT
Definition: ndis.h:50
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
struct _tagvirtio_net_hdr virtio_net_hdr_basic
#define VIRTIO_NET_F_HOST_UFO
Definition: ndis56common.h:107
LONGLONG QuadPart
Definition: typedefs.h:113
struct _tagIONetDescriptor * pIONetDescriptor
#define NDIS_PACKET_TYPE_DIRECTED
Definition: ndis.h:663
static NDIS_STATUS NTStatusToNdisStatus(NTSTATUS nt_status)
#define NDIS_PACKET_TYPE_BROADCAST
Definition: ndis.h:666
tBusResource PciBars[PCI_TYPE0_ADDRESSES]
Definition: ndis56common.h:170
BOOLEAN ParaNdis_ValidateMacAddress(PUCHAR pcMacAddress, BOOLEAN bLocal)
ULONG64 ifHCOutMulticastOctets
Definition: ndis56common.h:279
Definition: ps.c:97