win-pvdrivers

changeset 914:3c7778b9f877

Rename xennet* to xennet5* to prepare for creation of NDIS6 driver
author James Harper <james.harper@bendigoit.com.au>
date Sat Apr 30 10:57:23 2011 +1000 (2011-04-30)
parents dae0e5c1f26c
children a8a03b07dcfc
files xennet/sources xennet/xennet.c xennet/xennet5.c xennet/xennet5.h xennet/xennet5_common.c xennet/xennet5_oid.c xennet/xennet5_rx.c xennet/xennet5_tx.c xennet/xennet_common.c xennet/xennet_oid.c xennet/xennet_rx.c xennet/xennet_tx.c
line diff
     1.1 --- a/xennet/sources	Sat Apr 30 00:24:01 2011 +1000
     1.2 +++ b/xennet/sources	Sat Apr 30 10:57:23 2011 +1000
     1.3 @@ -12,5 +12,10 @@ TARGETLIBS=$(TARGETLIBS) $(LIBLFDS_DIR)\
     1.4  !ELSE
     1.5  TARGETLIBS=$(TARGETLIBS) $(LIBLFDS_DIR)\bin\AMD64\liblfds.lib
     1.6  !ENDIF
     1.7 +!IF "$(DDK_TARGET_OS)" == "Win2K" || "$(DDK_TARGET_OS)" == "WinXP" || "$(DDK_TARGET_OS)" == "WinNET"
     1.8 +C_DEFINES=$(C_DEFINES) -D_GPLPV_NDIS5
     1.9 +!ELSE
    1.10 +C_DEFINES=$(C_DEFINES) -D_GPLPV_NDIS6
    1.11 +!ENDIF
    1.12  NTTARGETFILES=$(NTTARGETFILES) $(OBJ_PATH)\$(O)\$(INF_NAME).inf
    1.13  SOURCES=xennet.rc xennet.c xennet_tx.c xennet_rx.c xennet_oid.c xennet_common.c
     2.1 --- a/xennet/xennet.c	Sat Apr 30 00:24:01 2011 +1000
     2.2 +++ b/xennet/xennet.c	Sat Apr 30 10:57:23 2011 +1000
     2.3 @@ -1,996 +1,5 @@
     2.4 -/*
     2.5 -PV Net Driver for Windows Xen HVM Domains
     2.6 -Copyright (C) 2007 James Harper
     2.7 -Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     2.8 -
     2.9 -This program is free software; you can redistribute it and/or
    2.10 -modify it under the terms of the GNU General Public License
    2.11 -as published by the Free Software Foundation; either version 2
    2.12 -of the License, or (at your option) any later version.
    2.13 -
    2.14 -This program is distributed in the hope that it will be useful,
    2.15 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.17 -GNU General Public License for more details.
    2.18 -
    2.19 -You should have received a copy of the GNU General Public License
    2.20 -along with this program; if not, write to the Free Software
    2.21 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    2.22 -*/
    2.23 -
    2.24 -#include <stdlib.h>
    2.25 -#include <io/xenbus.h>
    2.26 -#include "xennet.h"
    2.27 -
    2.28 -/* Not really necessary but keeps PREfast happy */
    2.29 -DRIVER_INITIALIZE DriverEntry;
    2.30 -static IO_WORKITEM_ROUTINE XenNet_ResumeWorkItem;
    2.31 -#if (VER_PRODUCTBUILD >= 7600)
    2.32 -static KDEFERRED_ROUTINE XenNet_SuspendResume;
    2.33 +#ifdef _GPLPV_NDIS5
    2.34 +#include "xennet5.c"
    2.35 +#else
    2.36 +#include "xennet6.c"
    2.37  #endif
    2.38 -
    2.39 -#pragma NDIS_INIT_FUNCTION(DriverEntry)
    2.40 -
    2.41 -/* ----- BEGIN Other people's code --------- */
    2.42 -/* from linux/include/linux/ctype.h, used under GPLv2 */
    2.43 -#define _U      0x01    /* upper */
    2.44 -#define _L      0x02    /* lower */
    2.45 -#define _D      0x04    /* digit */
    2.46 -#define _C      0x08    /* cntrl */
    2.47 -#define _P      0x10    /* punct */
    2.48 -#define _S      0x20    /* white space (space/lf/tab) */
    2.49 -#define _X      0x40    /* hex digit */
    2.50 -#define _SP     0x80    /* hard space (0x20) */
    2.51 -
    2.52 -/* from linux/include/lib/ctype.c, used under GPLv2 */
    2.53 -unsigned char _ctype[] = {
    2.54 -_C,_C,_C,_C,_C,_C,_C,_C,                        /* 0-7 */
    2.55 -_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,         /* 8-15 */
    2.56 -_C,_C,_C,_C,_C,_C,_C,_C,                        /* 16-23 */
    2.57 -_C,_C,_C,_C,_C,_C,_C,_C,                        /* 24-31 */
    2.58 -_S|_SP,_P,_P,_P,_P,_P,_P,_P,                    /* 32-39 */
    2.59 -_P,_P,_P,_P,_P,_P,_P,_P,                        /* 40-47 */
    2.60 -_D,_D,_D,_D,_D,_D,_D,_D,                        /* 48-55 */
    2.61 -_D,_D,_P,_P,_P,_P,_P,_P,                        /* 56-63 */
    2.62 -_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,      /* 64-71 */
    2.63 -_U,_U,_U,_U,_U,_U,_U,_U,                        /* 72-79 */
    2.64 -_U,_U,_U,_U,_U,_U,_U,_U,                        /* 80-87 */
    2.65 -_U,_U,_U,_P,_P,_P,_P,_P,                        /* 88-95 */
    2.66 -_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,      /* 96-103 */
    2.67 -_L,_L,_L,_L,_L,_L,_L,_L,                        /* 104-111 */
    2.68 -_L,_L,_L,_L,_L,_L,_L,_L,                        /* 112-119 */
    2.69 -_L,_L,_L,_P,_P,_P,_P,_C,                        /* 120-127 */
    2.70 -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 128-143 */
    2.71 -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 144-159 */
    2.72 -_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
    2.73 -_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
    2.74 -_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
    2.75 -_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
    2.76 -_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
    2.77 -_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
    2.78 -
    2.79 -/* from linux/include/linux/ctype.h, used under GPLv2 */
    2.80 -#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
    2.81 -
    2.82 -#define isalnum(c)      ((__ismask(c)&(_U|_L|_D)) != 0)
    2.83 -#define isalpha(c)      ((__ismask(c)&(_U|_L)) != 0)
    2.84 -#define iscntrl(c)      ((__ismask(c)&(_C)) != 0)
    2.85 -#define isdigit(c)      ((__ismask(c)&(_D)) != 0)
    2.86 -#define isgraph(c)      ((__ismask(c)&(_P|_U|_L|_D)) != 0)
    2.87 -#define islower(c)      ((__ismask(c)&(_L)) != 0)
    2.88 -#define isprint(c)      ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
    2.89 -#define ispunct(c)      ((__ismask(c)&(_P)) != 0)
    2.90 -#define isspace(c)      ((__ismask(c)&(_S)) != 0)
    2.91 -#define isupper(c)      ((__ismask(c)&(_U)) != 0)
    2.92 -#define isxdigit(c)     ((__ismask(c)&(_D|_X)) != 0)
    2.93 -
    2.94 -#define TOLOWER(x) ((x) | 0x20)
    2.95 -
    2.96 -/* from linux/lib/vsprintf.c, used under GPLv2 */
    2.97 -/* Copyright (C) 1991, 1992  Linus Torvalds
    2.98 - * Wirzenius wrote this portably, Torvalds fucked it up :-)
    2.99 - */
   2.100 -/**
   2.101 - * simple_strtoul - convert a string to an unsigned long
   2.102 - * @cp: The start of the string
   2.103 - * @endp: A pointer to the end of the parsed string will be placed here
   2.104 - * @base: The number base to use
   2.105 - */
   2.106 -unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
   2.107 -{
   2.108 -  unsigned long result = 0,value;
   2.109 -
   2.110 -  if (!base) {
   2.111 -    base = 10;
   2.112 -    if (*cp == '0') {
   2.113 -      base = 8;
   2.114 -      cp++;
   2.115 -      if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
   2.116 -        cp++;
   2.117 -        base = 16;
   2.118 -      }
   2.119 -    }
   2.120 -  } else if (base == 16) {
   2.121 -    if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
   2.122 -      cp += 2;
   2.123 -  }
   2.124 -  while (isxdigit(*cp) &&
   2.125 -    (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
   2.126 -    result = result*base + value;
   2.127 -    cp++;
   2.128 -  }
   2.129 -  if (endp)
   2.130 -    *endp = (char *)cp;
   2.131 -  return result;
   2.132 -}
   2.133 -/* end vsprintf.c code */
   2.134 -/* ----- END Other people's code --------- */
   2.135 -
   2.136 -static NDIS_STATUS
   2.137 -XenNet_ConnectBackend(struct xennet_info *xi)
   2.138 -{
   2.139 -  PUCHAR ptr;
   2.140 -  UCHAR type;
   2.141 -  PCHAR setting, value, value2;
   2.142 -  UINT i;
   2.143 -  ULONG backend_sg = 0;
   2.144 -  ULONG backend_gso = 0;
   2.145 -
   2.146 -  FUNCTION_ENTER();
   2.147 -  
   2.148 -  ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
   2.149 -
   2.150 -  ptr = xi->config_page;
   2.151 -  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
   2.152 -  {
   2.153 -    switch(type)
   2.154 -    {
   2.155 -    case XEN_INIT_TYPE_RING: /* frontend ring */
   2.156 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
   2.157 -      if (strcmp(setting, "tx-ring-ref") == 0)
   2.158 -      {
   2.159 -        FRONT_RING_INIT(&xi->tx, (netif_tx_sring_t *)value, PAGE_SIZE);
   2.160 -      } else if (strcmp(setting, "rx-ring-ref") == 0)
   2.161 -      {
   2.162 -        FRONT_RING_INIT(&xi->rx, (netif_rx_sring_t *)value, PAGE_SIZE);
   2.163 -      }
   2.164 -      break;
   2.165 -    case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
   2.166 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
   2.167 -      if (strcmp(setting, "event-channel") == 0)
   2.168 -      {
   2.169 -        xi->event_channel = PtrToUlong(value);
   2.170 -      }
   2.171 -      break;
   2.172 -    case XEN_INIT_TYPE_READ_STRING_FRONT:
   2.173 -      break;
   2.174 -    case XEN_INIT_TYPE_READ_STRING_BACK:
   2.175 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
   2.176 -      if (strcmp(setting, "mac") == 0)
   2.177 -      {
   2.178 -        char *s, *e;
   2.179 -        s = value;
   2.180 -        for (i = 0; i < ETH_ALEN; i++) {
   2.181 -          xi->perm_mac_addr[i] = (uint8_t)simple_strtoul(s, &e, 16);
   2.182 -          if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
   2.183 -            KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
   2.184 -          }
   2.185 -          s = e + 1;
   2.186 -        }
   2.187 -        if ((xi->curr_mac_addr[0] & 0x03) != 0x02)
   2.188 -        {
   2.189 -          /* only copy if curr_mac_addr is not a LUA */
   2.190 -          memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
   2.191 -        }
   2.192 -      }
   2.193 -      else if (strcmp(setting, "feature-sg") == 0)
   2.194 -      {
   2.195 -        if (atoi(value))
   2.196 -        {
   2.197 -          backend_sg = 1;
   2.198 -        }
   2.199 -      }
   2.200 -      else if (strcmp(setting, "feature-gso-tcpv4") == 0)
   2.201 -      {
   2.202 -        if (atoi(value))
   2.203 -        {
   2.204 -          backend_gso = 1;
   2.205 -        }
   2.206 -      }
   2.207 -      break;
   2.208 -    case XEN_INIT_TYPE_VECTORS:
   2.209 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   2.210 -      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   2.211 -        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   2.212 -      {
   2.213 -        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   2.214 -          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   2.215 -        FUNCTION_EXIT();
   2.216 -        return NDIS_STATUS_ADAPTER_NOT_FOUND;
   2.217 -      }
   2.218 -      else
   2.219 -        memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
   2.220 -      break;
   2.221 -    case XEN_INIT_TYPE_STATE_PTR:
   2.222 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   2.223 -      xi->device_state = (PXENPCI_DEVICE_STATE)value;
   2.224 -      break;
   2.225 -    default:
   2.226 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   2.227 -      break;
   2.228 -    }
   2.229 -  }
   2.230 -  if (xi->config_sg && !backend_sg)
   2.231 -  {
   2.232 -    KdPrint((__DRIVER_NAME "     SG not supported by backend - disabling\n"));
   2.233 -    xi->config_sg = 0;
   2.234 -  }
   2.235 -  if (xi->config_gso && !backend_gso)
   2.236 -  {
   2.237 -    KdPrint((__DRIVER_NAME "     GSO not supported by backend - disabling\n"));
   2.238 -    xi->config_gso = 0;
   2.239 -  }
   2.240 -  FUNCTION_EXIT();
   2.241 -  
   2.242 -  return NDIS_STATUS_SUCCESS;
   2.243 -}
   2.244 -
   2.245 -static VOID
   2.246 -XenNet_ResumeWorkItem(PDEVICE_OBJECT device_object, PVOID context)
   2.247 -{
   2.248 -  struct xennet_info *xi = context;
   2.249 -  KIRQL old_irql;
   2.250 -  
   2.251 -  UNREFERENCED_PARAMETER(device_object);
   2.252 -  
   2.253 -  FUNCTION_ENTER();
   2.254 -
   2.255 -  ASSERT(xi->resume_work_item);
   2.256 -
   2.257 -  IoFreeWorkItem(xi->resume_work_item);
   2.258 -  
   2.259 -  XenNet_TxResumeStart(xi);
   2.260 -  XenNet_RxResumeStart(xi);
   2.261 -  XenNet_ConnectBackend(xi);
   2.262 -  XenNet_RxResumeEnd(xi);
   2.263 -  XenNet_TxResumeEnd(xi);
   2.264 -
   2.265 -  KeAcquireSpinLock(&xi->resume_lock, &old_irql);
   2.266 -  xi->resume_work_item = NULL;
   2.267 -  KdPrint((__DRIVER_NAME "     *Setting suspend_resume_state_fdo = %d\n", xi->device_state->suspend_resume_state_pdo));
   2.268 -  xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
   2.269 -  KdPrint((__DRIVER_NAME "     *Notifying event channel %d\n", xi->device_state->pdo_event_channel));
   2.270 -  xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
   2.271 -  KeReleaseSpinLock(&xi->resume_lock, old_irql);
   2.272 -
   2.273 -  FUNCTION_EXIT();
   2.274 -
   2.275 -}
   2.276 -
   2.277 -static VOID
   2.278 -XenNet_SuspendResume(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
   2.279 -{
   2.280 -  struct xennet_info *xi = context;
   2.281 -  KIRQL old_irql;
   2.282 -  PIO_WORKITEM resume_work_item;
   2.283 -
   2.284 -  UNREFERENCED_PARAMETER(dpc);
   2.285 -  UNREFERENCED_PARAMETER(arg1);
   2.286 -  UNREFERENCED_PARAMETER(arg2);
   2.287 -
   2.288 -  FUNCTION_ENTER();
   2.289 -  
   2.290 -  switch (xi->device_state->suspend_resume_state_pdo)
   2.291 -  {
   2.292 -  case SR_STATE_SUSPENDING:
   2.293 -    KdPrint((__DRIVER_NAME "     New state SUSPENDING\n"));
   2.294 -    KeAcquireSpinLock(&xi->rx_lock, &old_irql);
   2.295 -    if (xi->rx_id_free == NET_RX_RING_SIZE)
   2.296 -    {  
   2.297 -      xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING;
   2.298 -      KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
   2.299 -      xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
   2.300 -    }
   2.301 -    KeReleaseSpinLock(&xi->rx_lock, old_irql);
   2.302 -    break;
   2.303 -  case SR_STATE_RESUMING:
   2.304 -    KdPrint((__DRIVER_NAME "     New state SR_STATE_RESUMING\n"));
   2.305 -    /* do it like this so we don't race and double-free the work item */
   2.306 -    resume_work_item = IoAllocateWorkItem(xi->fdo);
   2.307 -    KeAcquireSpinLock(&xi->resume_lock, &old_irql);
   2.308 -    if (xi->resume_work_item || xi->device_state->suspend_resume_state_fdo == SR_STATE_RESUMING)
   2.309 -    {
   2.310 -      KeReleaseSpinLock(&xi->resume_lock, old_irql);
   2.311 -      IoFreeWorkItem(resume_work_item);
   2.312 -      return;
   2.313 -    }
   2.314 -    xi->resume_work_item = resume_work_item;
   2.315 -    KeReleaseSpinLock(&xi->resume_lock, old_irql);
   2.316 -    IoQueueWorkItem(xi->resume_work_item, XenNet_ResumeWorkItem, DelayedWorkQueue, xi);
   2.317 -    break;
   2.318 -  default:
   2.319 -    KdPrint((__DRIVER_NAME "     New state %d\n", xi->device_state->suspend_resume_state_fdo));
   2.320 -    xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
   2.321 -    KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
   2.322 -    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
   2.323 -    break;
   2.324 -  }
   2.325 -  KeMemoryBarrier();
   2.326 -  
   2.327 -  FUNCTION_EXIT();
   2.328 -}
   2.329 -
   2.330 -static VOID
   2.331 -XenNet_RxTxDpc(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
   2.332 -{
   2.333 -  struct xennet_info *xi = context;
   2.334 -  BOOLEAN dont_set_event;
   2.335 -
   2.336 -  UNREFERENCED_PARAMETER(dpc);
   2.337 -  UNREFERENCED_PARAMETER(arg1);
   2.338 -  UNREFERENCED_PARAMETER(arg2);
   2.339 -
   2.340 -  /* if Rx goes over its per-dpc quota then make sure TxBufferGC doesn't set an event as we are already guaranteed to be called again */
   2.341 -  dont_set_event = XenNet_RxBufferCheck(xi);
   2.342 -  XenNet_TxBufferGC(xi, dont_set_event);
   2.343 -} 
   2.344 -
   2.345 -static BOOLEAN
   2.346 -XenNet_HandleEvent(PVOID context)
   2.347 -{
   2.348 -  struct xennet_info *xi = context;
   2.349 -  ULONG suspend_resume_state_pdo;
   2.350 -  
   2.351 -  //FUNCTION_ENTER();
   2.352 -  suspend_resume_state_pdo = xi->device_state->suspend_resume_state_pdo;
   2.353 -  KeMemoryBarrier();
   2.354 -//  KdPrint((__DRIVER_NAME "     connected = %d, inactive = %d, suspend_resume_state_pdo = %d\n",
   2.355 -//    xi->connected, xi->inactive, suspend_resume_state_pdo));
   2.356 -  if (!xi->shutting_down && suspend_resume_state_pdo != xi->device_state->suspend_resume_state_fdo)
   2.357 -  {
   2.358 -    KeInsertQueueDpc(&xi->suspend_dpc, NULL, NULL);
   2.359 -  }
   2.360 -  if (xi->connected && !xi->inactive && suspend_resume_state_pdo != SR_STATE_RESUMING)
   2.361 -  {
   2.362 -    KeInsertQueueDpc(&xi->rxtx_dpc, NULL, NULL);
   2.363 -  }
   2.364 -  //FUNCTION_EXIT();
   2.365 -  return TRUE;
   2.366 -}
   2.367 -
   2.368 -VOID
   2.369 -XenNet_SetPower(PDEVICE_OBJECT device_object, PVOID context)
   2.370 -{
   2.371 -  NTSTATUS status = STATUS_SUCCESS;
   2.372 -  KIRQL old_irql;
   2.373 -  struct xennet_info *xi = context;
   2.374 -  
   2.375 -  FUNCTION_ENTER();
   2.376 -  UNREFERENCED_PARAMETER(device_object);
   2.377 -
   2.378 -  switch (xi->new_power_state)
   2.379 -  {
   2.380 -  case NdisDeviceStateD0:
   2.381 -    KdPrint(("       NdisDeviceStateD0\n"));
   2.382 -    status = XenNet_D0Entry(xi);
   2.383 -    break;
   2.384 -  case NdisDeviceStateD1:
   2.385 -    KdPrint(("       NdisDeviceStateD1\n"));
   2.386 -    if (xi->power_state == NdisDeviceStateD0)
   2.387 -      status = XenNet_D0Exit(xi);
   2.388 -    break;
   2.389 -  case NdisDeviceStateD2:
   2.390 -    KdPrint(("       NdisDeviceStateD2\n"));
   2.391 -    if (xi->power_state == NdisDeviceStateD0)
   2.392 -      status = XenNet_D0Exit(xi);
   2.393 -    break;
   2.394 -  case NdisDeviceStateD3:
   2.395 -    KdPrint(("       NdisDeviceStateD3\n"));
   2.396 -    if (xi->power_state == NdisDeviceStateD0)
   2.397 -      status = XenNet_D0Exit(xi);
   2.398 -    break;
   2.399 -  default:
   2.400 -    KdPrint(("       NdisDeviceState??\n"));
   2.401 -    status = NDIS_STATUS_NOT_SUPPORTED;
   2.402 -    break;
   2.403 -  }
   2.404 -  xi->power_state = xi->new_power_state;
   2.405 -
   2.406 -  old_irql = KeRaiseIrqlToDpcLevel();
   2.407 -  NdisMSetInformationComplete(xi->adapter_handle, status);
   2.408 -  KeLowerIrql(old_irql);
   2.409 -  
   2.410 -  FUNCTION_EXIT();
   2.411 -}
   2.412 -
   2.413 -NDIS_STATUS
   2.414 -XenNet_D0Entry(struct xennet_info *xi)
   2.415 -{
   2.416 -  NDIS_STATUS status;
   2.417 -  PUCHAR ptr;
   2.418 -  CHAR buf[128];
   2.419 -  
   2.420 -  FUNCTION_ENTER();
   2.421 -
   2.422 -  xi->shutting_down = FALSE;
   2.423 -  
   2.424 -  ptr = xi->config_page;
   2.425 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL, NULL);
   2.426 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL, NULL);
   2.427 -  #pragma warning(suppress:4054)
   2.428 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL, "event-channel", (PVOID)XenNet_HandleEvent, xi);
   2.429 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mac", NULL, NULL);
   2.430 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-sg", NULL, NULL);
   2.431 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-gso-tcpv4", NULL, NULL);
   2.432 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1", NULL);
   2.433 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1", NULL);
   2.434 -  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
   2.435 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf, NULL);
   2.436 -  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->config_sg);
   2.437 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf, NULL);
   2.438 -  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
   2.439 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf, NULL);
   2.440 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
   2.441 -  __ADD_XEN_INIT_UCHAR(&ptr, 0); /* no pre-connect required */
   2.442 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
   2.443 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
   2.444 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
   2.445 -  __ADD_XEN_INIT_UCHAR(&ptr, 20);
   2.446 -  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   2.447 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
   2.448 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
   2.449 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
   2.450 -  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   2.451 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   2.452 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   2.453 -  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   2.454 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
   2.455 -  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
   2.456 -  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   2.457 -  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   2.458 -  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
   2.459 -
   2.460 -  status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
   2.461 -  if (!NT_SUCCESS(status))
   2.462 -  {
   2.463 -    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   2.464 -    return status;
   2.465 -  }
   2.466 -
   2.467 -  status = XenNet_ConnectBackend(xi);
   2.468 -  
   2.469 -  if (!NT_SUCCESS(status))
   2.470 -  {
   2.471 -    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   2.472 -    return status;
   2.473 -  }
   2.474 -
   2.475 -  if (!xi->config_sg)
   2.476 -  {
   2.477 -    /* without SG, GSO can be a maximum of PAGE_SIZE */
   2.478 -    xi->config_gso = min(xi->config_gso, PAGE_SIZE);
   2.479 -  }
   2.480 -
   2.481 -  XenNet_TxInit(xi);
   2.482 -  XenNet_RxInit(xi);
   2.483 -
   2.484 -  xi->connected = TRUE;
   2.485 -
   2.486 -  KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
   2.487 -
   2.488 -  FUNCTION_EXIT();
   2.489 -
   2.490 -  return status;
   2.491 -}
   2.492 -
   2.493 -// Called at <= DISPATCH_LEVEL
   2.494 -static NDIS_STATUS
   2.495 -XenNet_Init(
   2.496 -  OUT PNDIS_STATUS OpenErrorStatus,
   2.497 -  OUT PUINT SelectedMediumIndex,
   2.498 -  IN PNDIS_MEDIUM MediumArray,
   2.499 -  IN UINT MediumArraySize,
   2.500 -  IN NDIS_HANDLE MiniportAdapterHandle,
   2.501 -  IN NDIS_HANDLE WrapperConfigurationContext
   2.502 -  )
   2.503 -{
   2.504 -  NDIS_STATUS status;
   2.505 -  BOOLEAN medium_found = FALSE;
   2.506 -  struct xennet_info *xi = NULL;
   2.507 -  UINT nrl_length;
   2.508 -  PNDIS_RESOURCE_LIST nrl;
   2.509 -  PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
   2.510 -  KIRQL irq_level = 0;
   2.511 -  ULONG irq_vector = 0;
   2.512 -  ULONG irq_mode = 0;
   2.513 -  NDIS_HANDLE config_handle;
   2.514 -  NDIS_STRING config_param_name;
   2.515 -  PNDIS_CONFIGURATION_PARAMETER config_param;
   2.516 -  ULONG i;
   2.517 -  PUCHAR ptr;
   2.518 -  UCHAR type;
   2.519 -  PCHAR setting, value;
   2.520 -  ULONG length;
   2.521 -  //CHAR buf[128];
   2.522 -  PVOID network_address;
   2.523 -  UINT network_address_length;
   2.524 -  BOOLEAN qemu_hide_filter = FALSE;
   2.525 -  ULONG qemu_hide_flags_value = 0;
   2.526 -  
   2.527 -  UNREFERENCED_PARAMETER(OpenErrorStatus);
   2.528 -
   2.529 -  FUNCTION_ENTER();
   2.530 -
   2.531 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   2.532 -
   2.533 -  /* deal with medium stuff */
   2.534 -  for (i = 0; i < MediumArraySize; i++)
   2.535 -  {
   2.536 -    if (MediumArray[i] == NdisMedium802_3)
   2.537 -    {
   2.538 -      medium_found = TRUE;
   2.539 -      break;
   2.540 -    }
   2.541 -  }
   2.542 -  if (!medium_found)
   2.543 -  {
   2.544 -    KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
   2.545 -    return NDIS_STATUS_UNSUPPORTED_MEDIA;
   2.546 -  }
   2.547 -  *SelectedMediumIndex = i;
   2.548 -
   2.549 -  /* Alloc memory for adapter private info */
   2.550 -  status = NdisAllocateMemoryWithTag((PVOID)&xi, sizeof(*xi), XENNET_POOL_TAG);
   2.551 -  if (!NT_SUCCESS(status))
   2.552 -  {
   2.553 -    KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
   2.554 -    status = NDIS_STATUS_RESOURCES;
   2.555 -    goto err;
   2.556 -  }
   2.557 -  RtlZeroMemory(xi, sizeof(*xi));
   2.558 -  xi->adapter_handle = MiniportAdapterHandle;
   2.559 -  xi->rx_target     = RX_DFL_MIN_TARGET;
   2.560 -  xi->rx_min_target = RX_DFL_MIN_TARGET;
   2.561 -  xi->rx_max_target = RX_MAX_TARGET;
   2.562 -  xi->inactive      = TRUE;
   2.563 -  NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi, 0, 0 /* the last zero is to give the next | something to | with */
   2.564 -#ifdef NDIS51_MINIPORT
   2.565 -    |NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
   2.566 -#endif
   2.567 -    |NDIS_ATTRIBUTE_DESERIALIZE
   2.568 -    |NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK
   2.569 -    |NDIS_ATTRIBUTE_BUS_MASTER,
   2.570 -    NdisInterfaceInternal);
   2.571 -  xi->multicast_list_size = 0;
   2.572 -  xi->current_lookahead = MIN_LOOKAHEAD_LENGTH;
   2.573 -
   2.574 -  nrl_length = 0;
   2.575 -  NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
   2.576 -    NULL, (PUINT)&nrl_length);
   2.577 -  KdPrint((__DRIVER_NAME "     nrl_length = %d\n", nrl_length));
   2.578 -  status = NdisAllocateMemoryWithTag((PVOID)&nrl, nrl_length, XENNET_POOL_TAG);
   2.579 -  if (status != NDIS_STATUS_SUCCESS)
   2.580 -  {
   2.581 -    KdPrint((__DRIVER_NAME "     Could not get allocate memory for Adapter Resources 0x%x\n", status));
   2.582 -    return NDIS_STATUS_RESOURCES;
   2.583 -  }
   2.584 -  NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
   2.585 -    nrl, (PUINT)&nrl_length);
   2.586 -  if (status != NDIS_STATUS_SUCCESS)
   2.587 -  {
   2.588 -    KdPrint((__DRIVER_NAME "     Could not get Adapter Resources 0x%x\n", status));
   2.589 -    return NDIS_STATUS_RESOURCES;
   2.590 -  }
   2.591 -  xi->event_channel = 0;
   2.592 -  xi->config_csum = 1;
   2.593 -  xi->config_csum_rx_check = 1;
   2.594 -  xi->config_sg = 1;
   2.595 -  xi->config_gso = 61440;
   2.596 -  xi->config_page = NULL;
   2.597 -  xi->config_rx_interrupt_moderation = 0;
   2.598 -  
   2.599 -  for (i = 0; i < nrl->Count; i++)
   2.600 -  {
   2.601 -    prd = &nrl->PartialDescriptors[i];
   2.602 -
   2.603 -    switch(prd->Type)
   2.604 -    {
   2.605 -    case CmResourceTypeInterrupt:
   2.606 -      irq_vector = prd->u.Interrupt.Vector;
   2.607 -      irq_level = (KIRQL)prd->u.Interrupt.Level;
   2.608 -      irq_mode = (prd->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?NdisInterruptLatched:NdisInterruptLevelSensitive;
   2.609 -      KdPrint((__DRIVER_NAME "     irq_vector = %03x, irq_level = %03x, irq_mode = %s\n", irq_vector, irq_level,
   2.610 -        (irq_mode == NdisInterruptLatched)?"NdisInterruptLatched":"NdisInterruptLevelSensitive"));
   2.611 -      break;
   2.612 -    case CmResourceTypeMemory:
   2.613 -      if (xi->config_page)
   2.614 -      {
   2.615 -        KdPrint(("More than one memory range\n"));
   2.616 -        return NDIS_STATUS_RESOURCES;
   2.617 -      }
   2.618 -      else
   2.619 -      {
   2.620 -        status = NdisMMapIoSpace(&xi->config_page, MiniportAdapterHandle, prd->u.Memory.Start, prd->u.Memory.Length);
   2.621 -        if (!NT_SUCCESS(status))
   2.622 -        {
   2.623 -          KdPrint(("NdisMMapIoSpace failed with 0x%x\n", status));
   2.624 -          NdisFreeMemory(nrl, nrl_length, 0);
   2.625 -          return NDIS_STATUS_RESOURCES;
   2.626 -        }
   2.627 -      }
   2.628 -      break;
   2.629 -    }
   2.630 -  }
   2.631 -  NdisFreeMemory(nrl, nrl_length, 0);
   2.632 -  if (!xi->config_page)
   2.633 -  {
   2.634 -    KdPrint(("No config page given\n"));
   2.635 -    return NDIS_STATUS_RESOURCES;
   2.636 -  }
   2.637 -
   2.638 -  KeInitializeDpc(&xi->suspend_dpc, XenNet_SuspendResume, xi);
   2.639 -  KeInitializeSpinLock(&xi->resume_lock);
   2.640 -
   2.641 -  KeInitializeDpc(&xi->rxtx_dpc, XenNet_RxTxDpc, xi);
   2.642 -  KeSetTargetProcessorDpc(&xi->rxtx_dpc, 0);
   2.643 -  KeSetImportanceDpc(&xi->rxtx_dpc, HighImportance);
   2.644 -
   2.645 -  NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
   2.646 -    &xi->lower_do, NULL, NULL);
   2.647 -  xi->packet_filter = 0;
   2.648 -
   2.649 -  status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
   2.650 -    NAME_SIZE, xi->dev_desc, &length);
   2.651 -  if (!NT_SUCCESS(status))
   2.652 -  {
   2.653 -    KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
   2.654 -    status = NDIS_STATUS_FAILURE;
   2.655 -    goto err;
   2.656 -  }
   2.657 -
   2.658 -  ptr = xi->config_page;
   2.659 -  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value)) != XEN_INIT_TYPE_END)
   2.660 -  {
   2.661 -    switch(type)
   2.662 -    {
   2.663 -    case XEN_INIT_TYPE_VECTORS:
   2.664 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   2.665 -      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   2.666 -        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   2.667 -      {
   2.668 -        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   2.669 -          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   2.670 -        FUNCTION_EXIT();
   2.671 -        return NDIS_STATUS_FAILURE;
   2.672 -      }
   2.673 -      else
   2.674 -        memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
   2.675 -      break;
   2.676 -    case XEN_INIT_TYPE_STATE_PTR:
   2.677 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   2.678 -      xi->device_state = (PXENPCI_DEVICE_STATE)value;
   2.679 -      break;
   2.680 -    case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
   2.681 -      qemu_hide_flags_value = PtrToUlong(value);
   2.682 -      break;
   2.683 -    case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
   2.684 -      qemu_hide_filter = TRUE;
   2.685 -      break;
   2.686 -    default:
   2.687 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   2.688 -      break;
   2.689 -    }
   2.690 -  }
   2.691 -
   2.692 -  if ((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) || qemu_hide_filter)
   2.693 -    xi->inactive = FALSE;
   2.694 -
   2.695 -  xi->power_state = NdisDeviceStateD0;
   2.696 -  xi->power_workitem = IoAllocateWorkItem(xi->fdo);
   2.697 -
   2.698 -  // now build config page
   2.699 -  
   2.700 -  NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
   2.701 -  if (!NT_SUCCESS(status))
   2.702 -  {
   2.703 -    KdPrint(("Could not open config in registry (%08x)\n", status));
   2.704 -    status = NDIS_STATUS_RESOURCES;
   2.705 -    goto err;
   2.706 -  }
   2.707 -
   2.708 -  NdisInitUnicodeString(&config_param_name, L"ScatterGather");
   2.709 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   2.710 -  if (!NT_SUCCESS(status))
   2.711 -  {
   2.712 -    KdPrint(("Could not read ScatterGather value (%08x)\n", status));
   2.713 -    xi->config_sg = 1;
   2.714 -  }
   2.715 -  else
   2.716 -  {
   2.717 -    KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData));
   2.718 -    xi->config_sg = config_param->ParameterData.IntegerData;
   2.719 -  }
   2.720 -  
   2.721 -  NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
   2.722 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   2.723 -  if (!NT_SUCCESS(status))
   2.724 -  {
   2.725 -    KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
   2.726 -    xi->config_gso = 0;
   2.727 -  }
   2.728 -  else
   2.729 -  {
   2.730 -    KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
   2.731 -    xi->config_gso = config_param->ParameterData.IntegerData;
   2.732 -    if (xi->config_gso > 61440)
   2.733 -    {
   2.734 -      xi->config_gso = 61440;
   2.735 -      KdPrint(("(clipped to %d)\n", xi->config_gso));
   2.736 -    }
   2.737 -  }
   2.738 -
   2.739 -  NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
   2.740 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   2.741 -  if (!NT_SUCCESS(status))
   2.742 -  {
   2.743 -    KdPrint(("Could not read ChecksumOffload value (%08x)\n", status));
   2.744 -    xi->config_csum = 1;
   2.745 -  }
   2.746 -  else
   2.747 -  {
   2.748 -    KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData));
   2.749 -    xi->config_csum = !!config_param->ParameterData.IntegerData;
   2.750 -  }
   2.751 -
   2.752 -  NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadRxCheck");
   2.753 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   2.754 -  if (!NT_SUCCESS(status))
   2.755 -  {
   2.756 -    KdPrint(("Could not read ChecksumOffloadRxCheck value (%08x)\n", status));
   2.757 -    xi->config_csum_rx_check = 1;
   2.758 -  }
   2.759 -  else
   2.760 -  {
   2.761 -    KdPrint(("ChecksumOffloadRxCheck = %d\n", config_param->ParameterData.IntegerData));
   2.762 -    xi->config_csum_rx_check = !!config_param->ParameterData.IntegerData;
   2.763 -  }
   2.764 -
   2.765 -  NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadDontFix");
   2.766 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   2.767 -  if (!NT_SUCCESS(status))
   2.768 -  {
   2.769 -    KdPrint(("Could not read ChecksumOffloadDontFix value (%08x)\n", status));
   2.770 -    xi->config_csum_rx_dont_fix = 0;
   2.771 -  }
   2.772 -  else
   2.773 -  {
   2.774 -    KdPrint(("ChecksumOffloadDontFix = %d\n", config_param->ParameterData.IntegerData));
   2.775 -    xi->config_csum_rx_dont_fix = !!config_param->ParameterData.IntegerData;
   2.776 -  }
   2.777 -  
   2.778 -  
   2.779 -  
   2.780 -  NdisInitUnicodeString(&config_param_name, L"MTU");
   2.781 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);  
   2.782 -  if (!NT_SUCCESS(status))
   2.783 -  {
   2.784 -    KdPrint(("Could not read MTU value (%08x)\n", status));
   2.785 -    xi->config_mtu = 1500;
   2.786 -  }
   2.787 -  else
   2.788 -  {
   2.789 -    KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData));
   2.790 -    xi->config_mtu = config_param->ParameterData.IntegerData;
   2.791 -  }
   2.792 -
   2.793 -  NdisInitUnicodeString(&config_param_name, L"RxInterruptModeration");
   2.794 -  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);  
   2.795 -  if (!NT_SUCCESS(status))
   2.796 -  {
   2.797 -    KdPrint(("Could not read RxInterruptModeration value (%08x)\n", status));
   2.798 -    xi->config_rx_interrupt_moderation = 1500;
   2.799 -  }
   2.800 -  else
   2.801 -  {
   2.802 -    KdPrint(("RxInterruptModeration = %d\n", config_param->ParameterData.IntegerData));
   2.803 -    xi->config_rx_interrupt_moderation = config_param->ParameterData.IntegerData;
   2.804 -  }
   2.805 -  
   2.806 -
   2.807 -  NdisReadNetworkAddress(&status, &network_address, &network_address_length, config_handle);
   2.808 -  if (!NT_SUCCESS(status) || network_address_length != ETH_ALEN || ((((PUCHAR)network_address)[0] & 0x03) != 0x02))
   2.809 -  {
   2.810 -    KdPrint(("Could not read NetworkAddress value (%08x) or value is invalid\n", status));
   2.811 -    memset(xi->curr_mac_addr, 0, ETH_ALEN);
   2.812 -  }
   2.813 -  else
   2.814 -  {
   2.815 -    memcpy(xi->curr_mac_addr, network_address, ETH_ALEN);
   2.816 -    KdPrint(("     Set MAC address from registry to %02X:%02X:%02X:%02X:%02X:%02X\n",
   2.817 -      xi->curr_mac_addr[0], xi->curr_mac_addr[1], xi->curr_mac_addr[2], 
   2.818 -      xi->curr_mac_addr[3], xi->curr_mac_addr[4], xi->curr_mac_addr[5]));
   2.819 -  }
   2.820 -
   2.821 -  xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE);
   2.822 -  
   2.823 -  NdisCloseConfiguration(config_handle);
   2.824 -
   2.825 -  status = XenNet_D0Entry(xi);
   2.826 -  if (!NT_SUCCESS(status))
   2.827 -  {
   2.828 -    KdPrint(("Failed to go to D0 (%08x)\n", status));
   2.829 -    goto err;
   2.830 -  }
   2.831 -  return NDIS_STATUS_SUCCESS;
   2.832 -  
   2.833 -err:
   2.834 -  NdisFreeMemory(xi, 0, 0);
   2.835 -  *OpenErrorStatus = status;
   2.836 -  FUNCTION_EXIT_STATUS(status);
   2.837 -  return status;
   2.838 -}
   2.839 -
   2.840 -VOID
   2.841 -XenNet_PnPEventNotify(
   2.842 -  IN NDIS_HANDLE MiniportAdapterContext,
   2.843 -  IN NDIS_DEVICE_PNP_EVENT PnPEvent,
   2.844 -  IN PVOID InformationBuffer,
   2.845 -  IN ULONG InformationBufferLength
   2.846 -  )
   2.847 -{
   2.848 -  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   2.849 -  UNREFERENCED_PARAMETER(PnPEvent);
   2.850 -  UNREFERENCED_PARAMETER(InformationBuffer);
   2.851 -  UNREFERENCED_PARAMETER(InformationBufferLength);
   2.852 -
   2.853 -  FUNCTION_ENTER();
   2.854 -  switch (PnPEvent)
   2.855 -  {
   2.856 -  case NdisDevicePnPEventSurpriseRemoved:
   2.857 -    KdPrint((__DRIVER_NAME "     NdisDevicePnPEventSurpriseRemoved\n"));
   2.858 -    break;
   2.859 -  case NdisDevicePnPEventPowerProfileChanged :
   2.860 -    KdPrint((__DRIVER_NAME "     NdisDevicePnPEventPowerProfileChanged\n"));
   2.861 -    break;
   2.862 -  default:
   2.863 -    KdPrint((__DRIVER_NAME "     %d\n", PnPEvent));
   2.864 -    break;
   2.865 -  }
   2.866 -  FUNCTION_EXIT();
   2.867 -}
   2.868 -
   2.869 -/* Called when machine is shutting down, so just quiesce the HW and be done fast. */
   2.870 -VOID
   2.871 -XenNet_Shutdown(
   2.872 -  IN NDIS_HANDLE MiniportAdapterContext
   2.873 -  )
   2.874 -{
   2.875 -  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   2.876 -
   2.877 -  /* remember we are called at >= DIRQL here */
   2.878 -  FUNCTION_ENTER();
   2.879 -  FUNCTION_EXIT();
   2.880 -}
   2.881 -
   2.882 -/* Opposite of XenNet_Init */
   2.883 -VOID
   2.884 -XenNet_Halt(
   2.885 -  IN NDIS_HANDLE MiniportAdapterContext
   2.886 -  )
   2.887 -{
   2.888 -  struct xennet_info *xi = MiniportAdapterContext;
   2.889 -
   2.890 -  FUNCTION_ENTER();
   2.891 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   2.892 -  
   2.893 -  XenNet_D0Exit(xi);
   2.894 -
   2.895 -  NdisFreeMemory(xi, 0, 0);
   2.896 -
   2.897 -  FUNCTION_EXIT();
   2.898 -}
   2.899 -
   2.900 -NDIS_STATUS
   2.901 -XenNet_D0Exit(struct xennet_info *xi)
   2.902 -{
   2.903 -  FUNCTION_ENTER();
   2.904 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   2.905 -
   2.906 -  xi->shutting_down = TRUE;
   2.907 -  KeMemoryBarrier(); /* make sure everyone sees that we are now shutting down */
   2.908 -
   2.909 -  XenNet_TxShutdown(xi);
   2.910 -  XenNet_RxShutdown(xi);
   2.911 -
   2.912 -  xi->connected = FALSE;
   2.913 -  KeMemoryBarrier(); /* make sure everyone sees that we are now disconnected */
   2.914 -
   2.915 -  xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
   2.916 -
   2.917 -  FUNCTION_EXIT();
   2.918 -  
   2.919 -  return STATUS_SUCCESS;
   2.920 -}
   2.921 -
   2.922 -NDIS_STATUS 
   2.923 -XenNet_Reset(
   2.924 -  PBOOLEAN  AddressingReset,
   2.925 -  NDIS_HANDLE  MiniportAdapterContext
   2.926 -)
   2.927 -{
   2.928 -  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   2.929 -
   2.930 -  *AddressingReset = FALSE;
   2.931 -  return NDIS_STATUS_SUCCESS;
   2.932 -}
   2.933 -
   2.934 -NTSTATUS
   2.935 -DriverEntry(
   2.936 -  PDRIVER_OBJECT DriverObject,
   2.937 -  PUNICODE_STRING RegistryPath
   2.938 -  )
   2.939 -{
   2.940 -  NTSTATUS status;  
   2.941 -  NDIS_HANDLE ndis_wrapper_handle = NULL;
   2.942 -  NDIS_MINIPORT_CHARACTERISTICS mini_chars;
   2.943 -
   2.944 -  FUNCTION_ENTER();
   2.945 -
   2.946 -  KdPrint((__DRIVER_NAME "     DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
   2.947 -  
   2.948 -  NdisZeroMemory(&mini_chars, sizeof(mini_chars));
   2.949 -
   2.950 -  KdPrint((__DRIVER_NAME "     NdisGetVersion = %x\n", NdisGetVersion()));
   2.951 -
   2.952 -  KdPrint((__DRIVER_NAME "     ndis_wrapper_handle = %p\n", ndis_wrapper_handle));
   2.953 -  NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
   2.954 -  KdPrint((__DRIVER_NAME "     ndis_wrapper_handle = %p\n", ndis_wrapper_handle));
   2.955 -  if (!ndis_wrapper_handle)
   2.956 -  {
   2.957 -    KdPrint((__DRIVER_NAME "     NdisMInitializeWrapper failed\n"));
   2.958 -    return NDIS_STATUS_FAILURE;
   2.959 -  }
   2.960 -  KdPrint((__DRIVER_NAME "     NdisMInitializeWrapper succeeded\n"));
   2.961 -
   2.962 -  /* NDIS 5.1 driver */
   2.963 -  mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
   2.964 -  mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
   2.965 -
   2.966 -  KdPrint((__DRIVER_NAME "     MajorNdisVersion = %d,  MinorNdisVersion = %d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION));
   2.967 -
   2.968 -  mini_chars.HaltHandler = XenNet_Halt;
   2.969 -  mini_chars.InitializeHandler = XenNet_Init;
   2.970 -  //mini_chars.ISRHandler = XenNet_InterruptIsr;
   2.971 -  //mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
   2.972 -  mini_chars.QueryInformationHandler = XenNet_QueryInformation;
   2.973 -  mini_chars.ResetHandler = XenNet_Reset;
   2.974 -  mini_chars.SetInformationHandler = XenNet_SetInformation;
   2.975 -  /* added in v.4 -- use multiple pkts interface */
   2.976 -  mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
   2.977 -  mini_chars.SendPacketsHandler = XenNet_SendPackets;
   2.978 -  /* don't support cancel - no point as packets are never queued for long */
   2.979 -  //mini_chars.CancelSendPacketsHandler = XenNet_CancelSendPackets;
   2.980 -
   2.981 -#ifdef NDIS51_MINIPORT
   2.982 -  /* added in v.5.1 */
   2.983 -  mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
   2.984 -  mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
   2.985 -#else
   2.986 -  // something else here
   2.987 -#endif
   2.988 -
   2.989 -  /* set up upper-edge interface */
   2.990 -  KdPrint((__DRIVER_NAME "     about to call NdisMRegisterMiniport\n"));
   2.991 -  status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
   2.992 -  KdPrint((__DRIVER_NAME "     called NdisMRegisterMiniport\n"));
   2.993 -  if (!NT_SUCCESS(status))
   2.994 -  {
   2.995 -    KdPrint((__DRIVER_NAME "     NdisMRegisterMiniport failed, status = 0x%x\n", status));
   2.996 -    NdisTerminateWrapper(ndis_wrapper_handle, NULL);
   2.997 -    return status;
   2.998 -  }
   2.999 -
  2.1000 -  FUNCTION_EXIT();
  2.1001 -
  2.1002 -  return status;
  2.1003 -}
  2.1004 \ No newline at end of file
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xennet/xennet5.c	Sat Apr 30 10:57:23 2011 +1000
     3.3 @@ -0,0 +1,996 @@
     3.4 +/*
     3.5 +PV Net Driver for Windows Xen HVM Domains
     3.6 +Copyright (C) 2007 James Harper
     3.7 +Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     3.8 +
     3.9 +This program is free software; you can redistribute it and/or
    3.10 +modify it under the terms of the GNU General Public License
    3.11 +as published by the Free Software Foundation; either version 2
    3.12 +of the License, or (at your option) any later version.
    3.13 +
    3.14 +This program is distributed in the hope that it will be useful,
    3.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 +GNU General Public License for more details.
    3.18 +
    3.19 +You should have received a copy of the GNU General Public License
    3.20 +along with this program; if not, write to the Free Software
    3.21 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    3.22 +*/
    3.23 +
    3.24 +#include <stdlib.h>
    3.25 +#include <io/xenbus.h>
    3.26 +#include "xennet5.h"
    3.27 +
    3.28 +/* Not really necessary but keeps PREfast happy */
    3.29 +DRIVER_INITIALIZE DriverEntry;
    3.30 +static IO_WORKITEM_ROUTINE XenNet_ResumeWorkItem;
    3.31 +#if (VER_PRODUCTBUILD >= 7600)
    3.32 +static KDEFERRED_ROUTINE XenNet_SuspendResume;
    3.33 +#endif
    3.34 +
    3.35 +#pragma NDIS_INIT_FUNCTION(DriverEntry)
    3.36 +
    3.37 +/* ----- BEGIN Other people's code --------- */
    3.38 +/* from linux/include/linux/ctype.h, used under GPLv2 */
    3.39 +#define _U      0x01    /* upper */
    3.40 +#define _L      0x02    /* lower */
    3.41 +#define _D      0x04    /* digit */
    3.42 +#define _C      0x08    /* cntrl */
    3.43 +#define _P      0x10    /* punct */
    3.44 +#define _S      0x20    /* white space (space/lf/tab) */
    3.45 +#define _X      0x40    /* hex digit */
    3.46 +#define _SP     0x80    /* hard space (0x20) */
    3.47 +
    3.48 +/* from linux/include/lib/ctype.c, used under GPLv2 */
    3.49 +unsigned char _ctype[] = {
    3.50 +_C,_C,_C,_C,_C,_C,_C,_C,                        /* 0-7 */
    3.51 +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,         /* 8-15 */
    3.52 +_C,_C,_C,_C,_C,_C,_C,_C,                        /* 16-23 */
    3.53 +_C,_C,_C,_C,_C,_C,_C,_C,                        /* 24-31 */
    3.54 +_S|_SP,_P,_P,_P,_P,_P,_P,_P,                    /* 32-39 */
    3.55 +_P,_P,_P,_P,_P,_P,_P,_P,                        /* 40-47 */
    3.56 +_D,_D,_D,_D,_D,_D,_D,_D,                        /* 48-55 */
    3.57 +_D,_D,_P,_P,_P,_P,_P,_P,                        /* 56-63 */
    3.58 +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,      /* 64-71 */
    3.59 +_U,_U,_U,_U,_U,_U,_U,_U,                        /* 72-79 */
    3.60 +_U,_U,_U,_U,_U,_U,_U,_U,                        /* 80-87 */
    3.61 +_U,_U,_U,_P,_P,_P,_P,_P,                        /* 88-95 */
    3.62 +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,      /* 96-103 */
    3.63 +_L,_L,_L,_L,_L,_L,_L,_L,                        /* 104-111 */
    3.64 +_L,_L,_L,_L,_L,_L,_L,_L,                        /* 112-119 */
    3.65 +_L,_L,_L,_P,_P,_P,_P,_C,                        /* 120-127 */
    3.66 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 128-143 */
    3.67 +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 144-159 */
    3.68 +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
    3.69 +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
    3.70 +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
    3.71 +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
    3.72 +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
    3.73 +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
    3.74 +
    3.75 +/* from linux/include/linux/ctype.h, used under GPLv2 */
    3.76 +#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
    3.77 +
    3.78 +#define isalnum(c)      ((__ismask(c)&(_U|_L|_D)) != 0)
    3.79 +#define isalpha(c)      ((__ismask(c)&(_U|_L)) != 0)
    3.80 +#define iscntrl(c)      ((__ismask(c)&(_C)) != 0)
    3.81 +#define isdigit(c)      ((__ismask(c)&(_D)) != 0)
    3.82 +#define isgraph(c)      ((__ismask(c)&(_P|_U|_L|_D)) != 0)
    3.83 +#define islower(c)      ((__ismask(c)&(_L)) != 0)
    3.84 +#define isprint(c)      ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
    3.85 +#define ispunct(c)      ((__ismask(c)&(_P)) != 0)
    3.86 +#define isspace(c)      ((__ismask(c)&(_S)) != 0)
    3.87 +#define isupper(c)      ((__ismask(c)&(_U)) != 0)
    3.88 +#define isxdigit(c)     ((__ismask(c)&(_D|_X)) != 0)
    3.89 +
    3.90 +#define TOLOWER(x) ((x) | 0x20)
    3.91 +
    3.92 +/* from linux/lib/vsprintf.c, used under GPLv2 */
    3.93 +/* Copyright (C) 1991, 1992  Linus Torvalds
    3.94 + * Wirzenius wrote this portably, Torvalds fucked it up :-)
    3.95 + */
    3.96 +/**
    3.97 + * simple_strtoul - convert a string to an unsigned long
    3.98 + * @cp: The start of the string
    3.99 + * @endp: A pointer to the end of the parsed string will be placed here
   3.100 + * @base: The number base to use
   3.101 + */
   3.102 +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
   3.103 +{
   3.104 +  unsigned long result = 0,value;
   3.105 +
   3.106 +  if (!base) {
   3.107 +    base = 10;
   3.108 +    if (*cp == '0') {
   3.109 +      base = 8;
   3.110 +      cp++;
   3.111 +      if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
   3.112 +        cp++;
   3.113 +        base = 16;
   3.114 +      }
   3.115 +    }
   3.116 +  } else if (base == 16) {
   3.117 +    if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
   3.118 +      cp += 2;
   3.119 +  }
   3.120 +  while (isxdigit(*cp) &&
   3.121 +    (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
   3.122 +    result = result*base + value;
   3.123 +    cp++;
   3.124 +  }
   3.125 +  if (endp)
   3.126 +    *endp = (char *)cp;
   3.127 +  return result;
   3.128 +}
   3.129 +/* end vsprintf.c code */
   3.130 +/* ----- END Other people's code --------- */
   3.131 +
   3.132 +static NDIS_STATUS
   3.133 +XenNet_ConnectBackend(struct xennet_info *xi)
   3.134 +{
   3.135 +  PUCHAR ptr;
   3.136 +  UCHAR type;
   3.137 +  PCHAR setting, value, value2;
   3.138 +  UINT i;
   3.139 +  ULONG backend_sg = 0;
   3.140 +  ULONG backend_gso = 0;
   3.141 +
   3.142 +  FUNCTION_ENTER();
   3.143 +  
   3.144 +  ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
   3.145 +
   3.146 +  ptr = xi->config_page;
   3.147 +  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
   3.148 +  {
   3.149 +    switch(type)
   3.150 +    {
   3.151 +    case XEN_INIT_TYPE_RING: /* frontend ring */
   3.152 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
   3.153 +      if (strcmp(setting, "tx-ring-ref") == 0)
   3.154 +      {
   3.155 +        FRONT_RING_INIT(&xi->tx, (netif_tx_sring_t *)value, PAGE_SIZE);
   3.156 +      } else if (strcmp(setting, "rx-ring-ref") == 0)
   3.157 +      {
   3.158 +        FRONT_RING_INIT(&xi->rx, (netif_rx_sring_t *)value, PAGE_SIZE);
   3.159 +      }
   3.160 +      break;
   3.161 +    case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
   3.162 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
   3.163 +      if (strcmp(setting, "event-channel") == 0)
   3.164 +      {
   3.165 +        xi->event_channel = PtrToUlong(value);
   3.166 +      }
   3.167 +      break;
   3.168 +    case XEN_INIT_TYPE_READ_STRING_FRONT:
   3.169 +      break;
   3.170 +    case XEN_INIT_TYPE_READ_STRING_BACK:
   3.171 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
   3.172 +      if (strcmp(setting, "mac") == 0)
   3.173 +      {
   3.174 +        char *s, *e;
   3.175 +        s = value;
   3.176 +        for (i = 0; i < ETH_ALEN; i++) {
   3.177 +          xi->perm_mac_addr[i] = (uint8_t)simple_strtoul(s, &e, 16);
   3.178 +          if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
   3.179 +            KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
   3.180 +          }
   3.181 +          s = e + 1;
   3.182 +        }
   3.183 +        if ((xi->curr_mac_addr[0] & 0x03) != 0x02)
   3.184 +        {
   3.185 +          /* only copy if curr_mac_addr is not a LUA */
   3.186 +          memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
   3.187 +        }
   3.188 +      }
   3.189 +      else if (strcmp(setting, "feature-sg") == 0)
   3.190 +      {
   3.191 +        if (atoi(value))
   3.192 +        {
   3.193 +          backend_sg = 1;
   3.194 +        }
   3.195 +      }
   3.196 +      else if (strcmp(setting, "feature-gso-tcpv4") == 0)
   3.197 +      {
   3.198 +        if (atoi(value))
   3.199 +        {
   3.200 +          backend_gso = 1;
   3.201 +        }
   3.202 +      }
   3.203 +      break;
   3.204 +    case XEN_INIT_TYPE_VECTORS:
   3.205 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   3.206 +      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   3.207 +        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   3.208 +      {
   3.209 +        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   3.210 +          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   3.211 +        FUNCTION_EXIT();
   3.212 +        return NDIS_STATUS_ADAPTER_NOT_FOUND;
   3.213 +      }
   3.214 +      else
   3.215 +        memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
   3.216 +      break;
   3.217 +    case XEN_INIT_TYPE_STATE_PTR:
   3.218 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   3.219 +      xi->device_state = (PXENPCI_DEVICE_STATE)value;
   3.220 +      break;
   3.221 +    default:
   3.222 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   3.223 +      break;
   3.224 +    }
   3.225 +  }
   3.226 +  if (xi->config_sg && !backend_sg)
   3.227 +  {
   3.228 +    KdPrint((__DRIVER_NAME "     SG not supported by backend - disabling\n"));
   3.229 +    xi->config_sg = 0;
   3.230 +  }
   3.231 +  if (xi->config_gso && !backend_gso)
   3.232 +  {
   3.233 +    KdPrint((__DRIVER_NAME "     GSO not supported by backend - disabling\n"));
   3.234 +    xi->config_gso = 0;
   3.235 +  }
   3.236 +  FUNCTION_EXIT();
   3.237 +  
   3.238 +  return NDIS_STATUS_SUCCESS;
   3.239 +}
   3.240 +
   3.241 +static VOID
   3.242 +XenNet_ResumeWorkItem(PDEVICE_OBJECT device_object, PVOID context)
   3.243 +{
   3.244 +  struct xennet_info *xi = context;
   3.245 +  KIRQL old_irql;
   3.246 +  
   3.247 +  UNREFERENCED_PARAMETER(device_object);
   3.248 +  
   3.249 +  FUNCTION_ENTER();
   3.250 +
   3.251 +  ASSERT(xi->resume_work_item);
   3.252 +
   3.253 +  IoFreeWorkItem(xi->resume_work_item);
   3.254 +  
   3.255 +  XenNet_TxResumeStart(xi);
   3.256 +  XenNet_RxResumeStart(xi);
   3.257 +  XenNet_ConnectBackend(xi);
   3.258 +  XenNet_RxResumeEnd(xi);
   3.259 +  XenNet_TxResumeEnd(xi);
   3.260 +
   3.261 +  KeAcquireSpinLock(&xi->resume_lock, &old_irql);
   3.262 +  xi->resume_work_item = NULL;
   3.263 +  KdPrint((__DRIVER_NAME "     *Setting suspend_resume_state_fdo = %d\n", xi->device_state->suspend_resume_state_pdo));
   3.264 +  xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
   3.265 +  KdPrint((__DRIVER_NAME "     *Notifying event channel %d\n", xi->device_state->pdo_event_channel));
   3.266 +  xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
   3.267 +  KeReleaseSpinLock(&xi->resume_lock, old_irql);
   3.268 +
   3.269 +  FUNCTION_EXIT();
   3.270 +
   3.271 +}
   3.272 +
   3.273 +static VOID
   3.274 +XenNet_SuspendResume(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
   3.275 +{
   3.276 +  struct xennet_info *xi = context;
   3.277 +  KIRQL old_irql;
   3.278 +  PIO_WORKITEM resume_work_item;
   3.279 +
   3.280 +  UNREFERENCED_PARAMETER(dpc);
   3.281 +  UNREFERENCED_PARAMETER(arg1);
   3.282 +  UNREFERENCED_PARAMETER(arg2);
   3.283 +
   3.284 +  FUNCTION_ENTER();
   3.285 +  
   3.286 +  switch (xi->device_state->suspend_resume_state_pdo)
   3.287 +  {
   3.288 +  case SR_STATE_SUSPENDING:
   3.289 +    KdPrint((__DRIVER_NAME "     New state SUSPENDING\n"));
   3.290 +    KeAcquireSpinLock(&xi->rx_lock, &old_irql);
   3.291 +    if (xi->rx_id_free == NET_RX_RING_SIZE)
   3.292 +    {  
   3.293 +      xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING;
   3.294 +      KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
   3.295 +      xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
   3.296 +    }
   3.297 +    KeReleaseSpinLock(&xi->rx_lock, old_irql);
   3.298 +    break;
   3.299 +  case SR_STATE_RESUMING:
   3.300 +    KdPrint((__DRIVER_NAME "     New state SR_STATE_RESUMING\n"));
   3.301 +    /* do it like this so we don't race and double-free the work item */
   3.302 +    resume_work_item = IoAllocateWorkItem(xi->fdo);
   3.303 +    KeAcquireSpinLock(&xi->resume_lock, &old_irql);
   3.304 +    if (xi->resume_work_item || xi->device_state->suspend_resume_state_fdo == SR_STATE_RESUMING)
   3.305 +    {
   3.306 +      KeReleaseSpinLock(&xi->resume_lock, old_irql);
   3.307 +      IoFreeWorkItem(resume_work_item);
   3.308 +      return;
   3.309 +    }
   3.310 +    xi->resume_work_item = resume_work_item;
   3.311 +    KeReleaseSpinLock(&xi->resume_lock, old_irql);
   3.312 +    IoQueueWorkItem(xi->resume_work_item, XenNet_ResumeWorkItem, DelayedWorkQueue, xi);
   3.313 +    break;
   3.314 +  default:
   3.315 +    KdPrint((__DRIVER_NAME "     New state %d\n", xi->device_state->suspend_resume_state_fdo));
   3.316 +    xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
   3.317 +    KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
   3.318 +    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
   3.319 +    break;
   3.320 +  }
   3.321 +  KeMemoryBarrier();
   3.322 +  
   3.323 +  FUNCTION_EXIT();
   3.324 +}
   3.325 +
   3.326 +static VOID
   3.327 +XenNet_RxTxDpc(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
   3.328 +{
   3.329 +  struct xennet_info *xi = context;
   3.330 +  BOOLEAN dont_set_event;
   3.331 +
   3.332 +  UNREFERENCED_PARAMETER(dpc);
   3.333 +  UNREFERENCED_PARAMETER(arg1);
   3.334 +  UNREFERENCED_PARAMETER(arg2);
   3.335 +
   3.336 +  /* if Rx goes over its per-dpc quota then make sure TxBufferGC doesn't set an event as we are already guaranteed to be called again */
   3.337 +  dont_set_event = XenNet_RxBufferCheck(xi);
   3.338 +  XenNet_TxBufferGC(xi, dont_set_event);
   3.339 +} 
   3.340 +
   3.341 +static BOOLEAN
   3.342 +XenNet_HandleEvent(PVOID context)
   3.343 +{
   3.344 +  struct xennet_info *xi = context;
   3.345 +  ULONG suspend_resume_state_pdo;
   3.346 +  
   3.347 +  //FUNCTION_ENTER();
   3.348 +  suspend_resume_state_pdo = xi->device_state->suspend_resume_state_pdo;
   3.349 +  KeMemoryBarrier();
   3.350 +//  KdPrint((__DRIVER_NAME "     connected = %d, inactive = %d, suspend_resume_state_pdo = %d\n",
   3.351 +//    xi->connected, xi->inactive, suspend_resume_state_pdo));
   3.352 +  if (!xi->shutting_down && suspend_resume_state_pdo != xi->device_state->suspend_resume_state_fdo)
   3.353 +  {
   3.354 +    KeInsertQueueDpc(&xi->suspend_dpc, NULL, NULL);
   3.355 +  }
   3.356 +  if (xi->connected && !xi->inactive && suspend_resume_state_pdo != SR_STATE_RESUMING)
   3.357 +  {
   3.358 +    KeInsertQueueDpc(&xi->rxtx_dpc, NULL, NULL);
   3.359 +  }
   3.360 +  //FUNCTION_EXIT();
   3.361 +  return TRUE;
   3.362 +}
   3.363 +
   3.364 +VOID
   3.365 +XenNet_SetPower(PDEVICE_OBJECT device_object, PVOID context)
   3.366 +{
   3.367 +  NTSTATUS status = STATUS_SUCCESS;
   3.368 +  KIRQL old_irql;
   3.369 +  struct xennet_info *xi = context;
   3.370 +  
   3.371 +  FUNCTION_ENTER();
   3.372 +  UNREFERENCED_PARAMETER(device_object);
   3.373 +
   3.374 +  switch (xi->new_power_state)
   3.375 +  {
   3.376 +  case NdisDeviceStateD0:
   3.377 +    KdPrint(("       NdisDeviceStateD0\n"));
   3.378 +    status = XenNet_D0Entry(xi);
   3.379 +    break;
   3.380 +  case NdisDeviceStateD1:
   3.381 +    KdPrint(("       NdisDeviceStateD1\n"));
   3.382 +    if (xi->power_state == NdisDeviceStateD0)
   3.383 +      status = XenNet_D0Exit(xi);
   3.384 +    break;
   3.385 +  case NdisDeviceStateD2:
   3.386 +    KdPrint(("       NdisDeviceStateD2\n"));
   3.387 +    if (xi->power_state == NdisDeviceStateD0)
   3.388 +      status = XenNet_D0Exit(xi);
   3.389 +    break;
   3.390 +  case NdisDeviceStateD3:
   3.391 +    KdPrint(("       NdisDeviceStateD3\n"));
   3.392 +    if (xi->power_state == NdisDeviceStateD0)
   3.393 +      status = XenNet_D0Exit(xi);
   3.394 +    break;
   3.395 +  default:
   3.396 +    KdPrint(("       NdisDeviceState??\n"));
   3.397 +    status = NDIS_STATUS_NOT_SUPPORTED;
   3.398 +    break;
   3.399 +  }
   3.400 +  xi->power_state = xi->new_power_state;
   3.401 +
   3.402 +  old_irql = KeRaiseIrqlToDpcLevel();
   3.403 +  NdisMSetInformationComplete(xi->adapter_handle, status);
   3.404 +  KeLowerIrql(old_irql);
   3.405 +  
   3.406 +  FUNCTION_EXIT();
   3.407 +}
   3.408 +
   3.409 +NDIS_STATUS
   3.410 +XenNet_D0Entry(struct xennet_info *xi)
   3.411 +{
   3.412 +  NDIS_STATUS status;
   3.413 +  PUCHAR ptr;
   3.414 +  CHAR buf[128];
   3.415 +  
   3.416 +  FUNCTION_ENTER();
   3.417 +
   3.418 +  xi->shutting_down = FALSE;
   3.419 +  
   3.420 +  ptr = xi->config_page;
   3.421 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL, NULL);
   3.422 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL, NULL);
   3.423 +  #pragma warning(suppress:4054)
   3.424 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL, "event-channel", (PVOID)XenNet_HandleEvent, xi);
   3.425 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mac", NULL, NULL);
   3.426 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-sg", NULL, NULL);
   3.427 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-gso-tcpv4", NULL, NULL);
   3.428 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1", NULL);
   3.429 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1", NULL);
   3.430 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
   3.431 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf, NULL);
   3.432 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->config_sg);
   3.433 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf, NULL);
   3.434 +  RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
   3.435 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf, NULL);
   3.436 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
   3.437 +  __ADD_XEN_INIT_UCHAR(&ptr, 0); /* no pre-connect required */
   3.438 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
   3.439 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
   3.440 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
   3.441 +  __ADD_XEN_INIT_UCHAR(&ptr, 20);
   3.442 +  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   3.443 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
   3.444 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
   3.445 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
   3.446 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   3.447 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   3.448 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   3.449 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   3.450 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
   3.451 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
   3.452 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   3.453 +  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   3.454 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
   3.455 +
   3.456 +  status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
   3.457 +  if (!NT_SUCCESS(status))
   3.458 +  {
   3.459 +    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   3.460 +    return status;
   3.461 +  }
   3.462 +
   3.463 +  status = XenNet_ConnectBackend(xi);
   3.464 +  
   3.465 +  if (!NT_SUCCESS(status))
   3.466 +  {
   3.467 +    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   3.468 +    return status;
   3.469 +  }
   3.470 +
   3.471 +  if (!xi->config_sg)
   3.472 +  {
   3.473 +    /* without SG, GSO can be a maximum of PAGE_SIZE */
   3.474 +    xi->config_gso = min(xi->config_gso, PAGE_SIZE);
   3.475 +  }
   3.476 +
   3.477 +  XenNet_TxInit(xi);
   3.478 +  XenNet_RxInit(xi);
   3.479 +
   3.480 +  xi->connected = TRUE;
   3.481 +
   3.482 +  KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
   3.483 +
   3.484 +  FUNCTION_EXIT();
   3.485 +
   3.486 +  return status;
   3.487 +}
   3.488 +
   3.489 +// Called at <= DISPATCH_LEVEL
   3.490 +static NDIS_STATUS
   3.491 +XenNet_Init(
   3.492 +  OUT PNDIS_STATUS OpenErrorStatus,
   3.493 +  OUT PUINT SelectedMediumIndex,
   3.494 +  IN PNDIS_MEDIUM MediumArray,
   3.495 +  IN UINT MediumArraySize,
   3.496 +  IN NDIS_HANDLE MiniportAdapterHandle,
   3.497 +  IN NDIS_HANDLE WrapperConfigurationContext
   3.498 +  )
   3.499 +{
   3.500 +  NDIS_STATUS status;
   3.501 +  BOOLEAN medium_found = FALSE;
   3.502 +  struct xennet_info *xi = NULL;
   3.503 +  UINT nrl_length;
   3.504 +  PNDIS_RESOURCE_LIST nrl;
   3.505 +  PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
   3.506 +  KIRQL irq_level = 0;
   3.507 +  ULONG irq_vector = 0;
   3.508 +  ULONG irq_mode = 0;
   3.509 +  NDIS_HANDLE config_handle;
   3.510 +  NDIS_STRING config_param_name;
   3.511 +  PNDIS_CONFIGURATION_PARAMETER config_param;
   3.512 +  ULONG i;
   3.513 +  PUCHAR ptr;
   3.514 +  UCHAR type;
   3.515 +  PCHAR setting, value;
   3.516 +  ULONG length;
   3.517 +  //CHAR buf[128];
   3.518 +  PVOID network_address;
   3.519 +  UINT network_address_length;
   3.520 +  BOOLEAN qemu_hide_filter = FALSE;
   3.521 +  ULONG qemu_hide_flags_value = 0;
   3.522 +  
   3.523 +  UNREFERENCED_PARAMETER(OpenErrorStatus);
   3.524 +
   3.525 +  FUNCTION_ENTER();
   3.526 +
   3.527 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.528 +
   3.529 +  /* deal with medium stuff */
   3.530 +  for (i = 0; i < MediumArraySize; i++)
   3.531 +  {
   3.532 +    if (MediumArray[i] == NdisMedium802_3)
   3.533 +    {
   3.534 +      medium_found = TRUE;
   3.535 +      break;
   3.536 +    }
   3.537 +  }
   3.538 +  if (!medium_found)
   3.539 +  {
   3.540 +    KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
   3.541 +    return NDIS_STATUS_UNSUPPORTED_MEDIA;
   3.542 +  }
   3.543 +  *SelectedMediumIndex = i;
   3.544 +
   3.545 +  /* Alloc memory for adapter private info */
   3.546 +  status = NdisAllocateMemoryWithTag((PVOID)&xi, sizeof(*xi), XENNET_POOL_TAG);
   3.547 +  if (!NT_SUCCESS(status))
   3.548 +  {
   3.549 +    KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
   3.550 +    status = NDIS_STATUS_RESOURCES;
   3.551 +    goto err;
   3.552 +  }
   3.553 +  RtlZeroMemory(xi, sizeof(*xi));
   3.554 +  xi->adapter_handle = MiniportAdapterHandle;
   3.555 +  xi->rx_target     = RX_DFL_MIN_TARGET;
   3.556 +  xi->rx_min_target = RX_DFL_MIN_TARGET;
   3.557 +  xi->rx_max_target = RX_MAX_TARGET;
   3.558 +  xi->inactive      = TRUE;
   3.559 +  NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi, 0, 0 /* the last zero is to give the next | something to | with */
   3.560 +#ifdef NDIS51_MINIPORT
   3.561 +    |NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
   3.562 +#endif
   3.563 +    |NDIS_ATTRIBUTE_DESERIALIZE
   3.564 +    |NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK
   3.565 +    |NDIS_ATTRIBUTE_BUS_MASTER,
   3.566 +    NdisInterfaceInternal);
   3.567 +  xi->multicast_list_size = 0;
   3.568 +  xi->current_lookahead = MIN_LOOKAHEAD_LENGTH;
   3.569 +
   3.570 +  nrl_length = 0;
   3.571 +  NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
   3.572 +    NULL, (PUINT)&nrl_length);
   3.573 +  KdPrint((__DRIVER_NAME "     nrl_length = %d\n", nrl_length));
   3.574 +  status = NdisAllocateMemoryWithTag((PVOID)&nrl, nrl_length, XENNET_POOL_TAG);
   3.575 +  if (status != NDIS_STATUS_SUCCESS)
   3.576 +  {
   3.577 +    KdPrint((__DRIVER_NAME "     Could not get allocate memory for Adapter Resources 0x%x\n", status));
   3.578 +    return NDIS_STATUS_RESOURCES;
   3.579 +  }
   3.580 +  NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
   3.581 +    nrl, (PUINT)&nrl_length);
   3.582 +  if (status != NDIS_STATUS_SUCCESS)
   3.583 +  {
   3.584 +    KdPrint((__DRIVER_NAME "     Could not get Adapter Resources 0x%x\n", status));
   3.585 +    return NDIS_STATUS_RESOURCES;
   3.586 +  }
   3.587 +  xi->event_channel = 0;
   3.588 +  xi->config_csum = 1;
   3.589 +  xi->config_csum_rx_check = 1;
   3.590 +  xi->config_sg = 1;
   3.591 +  xi->config_gso = 61440;
   3.592 +  xi->config_page = NULL;
   3.593 +  xi->config_rx_interrupt_moderation = 0;
   3.594 +  
   3.595 +  for (i = 0; i < nrl->Count; i++)
   3.596 +  {
   3.597 +    prd = &nrl->PartialDescriptors[i];
   3.598 +
   3.599 +    switch(prd->Type)
   3.600 +    {
   3.601 +    case CmResourceTypeInterrupt:
   3.602 +      irq_vector = prd->u.Interrupt.Vector;
   3.603 +      irq_level = (KIRQL)prd->u.Interrupt.Level;
   3.604 +      irq_mode = (prd->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?NdisInterruptLatched:NdisInterruptLevelSensitive;
   3.605 +      KdPrint((__DRIVER_NAME "     irq_vector = %03x, irq_level = %03x, irq_mode = %s\n", irq_vector, irq_level,
   3.606 +        (irq_mode == NdisInterruptLatched)?"NdisInterruptLatched":"NdisInterruptLevelSensitive"));
   3.607 +      break;
   3.608 +    case CmResourceTypeMemory:
   3.609 +      if (xi->config_page)
   3.610 +      {
   3.611 +        KdPrint(("More than one memory range\n"));
   3.612 +        return NDIS_STATUS_RESOURCES;
   3.613 +      }
   3.614 +      else
   3.615 +      {
   3.616 +        status = NdisMMapIoSpace(&xi->config_page, MiniportAdapterHandle, prd->u.Memory.Start, prd->u.Memory.Length);
   3.617 +        if (!NT_SUCCESS(status))
   3.618 +        {
   3.619 +          KdPrint(("NdisMMapIoSpace failed with 0x%x\n", status));
   3.620 +          NdisFreeMemory(nrl, nrl_length, 0);
   3.621 +          return NDIS_STATUS_RESOURCES;
   3.622 +        }
   3.623 +      }
   3.624 +      break;
   3.625 +    }
   3.626 +  }
   3.627 +  NdisFreeMemory(nrl, nrl_length, 0);
   3.628 +  if (!xi->config_page)
   3.629 +  {
   3.630 +    KdPrint(("No config page given\n"));
   3.631 +    return NDIS_STATUS_RESOURCES;
   3.632 +  }
   3.633 +
   3.634 +  KeInitializeDpc(&xi->suspend_dpc, XenNet_SuspendResume, xi);
   3.635 +  KeInitializeSpinLock(&xi->resume_lock);
   3.636 +
   3.637 +  KeInitializeDpc(&xi->rxtx_dpc, XenNet_RxTxDpc, xi);
   3.638 +  KeSetTargetProcessorDpc(&xi->rxtx_dpc, 0);
   3.639 +  KeSetImportanceDpc(&xi->rxtx_dpc, HighImportance);
   3.640 +
   3.641 +  NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
   3.642 +    &xi->lower_do, NULL, NULL);
   3.643 +  xi->packet_filter = 0;
   3.644 +
   3.645 +  status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
   3.646 +    NAME_SIZE, xi->dev_desc, &length);
   3.647 +  if (!NT_SUCCESS(status))
   3.648 +  {
   3.649 +    KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
   3.650 +    status = NDIS_STATUS_FAILURE;
   3.651 +    goto err;
   3.652 +  }
   3.653 +
   3.654 +  ptr = xi->config_page;
   3.655 +  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value)) != XEN_INIT_TYPE_END)
   3.656 +  {
   3.657 +    switch(type)
   3.658 +    {
   3.659 +    case XEN_INIT_TYPE_VECTORS:
   3.660 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   3.661 +      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   3.662 +        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   3.663 +      {
   3.664 +        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   3.665 +          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   3.666 +        FUNCTION_EXIT();
   3.667 +        return NDIS_STATUS_FAILURE;
   3.668 +      }
   3.669 +      else
   3.670 +        memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
   3.671 +      break;
   3.672 +    case XEN_INIT_TYPE_STATE_PTR:
   3.673 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   3.674 +      xi->device_state = (PXENPCI_DEVICE_STATE)value;
   3.675 +      break;
   3.676 +    case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
   3.677 +      qemu_hide_flags_value = PtrToUlong(value);
   3.678 +      break;
   3.679 +    case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
   3.680 +      qemu_hide_filter = TRUE;
   3.681 +      break;
   3.682 +    default:
   3.683 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   3.684 +      break;
   3.685 +    }
   3.686 +  }
   3.687 +
   3.688 +  if ((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) || qemu_hide_filter)
   3.689 +    xi->inactive = FALSE;
   3.690 +
   3.691 +  xi->power_state = NdisDeviceStateD0;
   3.692 +  xi->power_workitem = IoAllocateWorkItem(xi->fdo);
   3.693 +
   3.694 +  // now build config page
   3.695 +  
   3.696 +  NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
   3.697 +  if (!NT_SUCCESS(status))
   3.698 +  {
   3.699 +    KdPrint(("Could not open config in registry (%08x)\n", status));
   3.700 +    status = NDIS_STATUS_RESOURCES;
   3.701 +    goto err;
   3.702 +  }
   3.703 +
   3.704 +  NdisInitUnicodeString(&config_param_name, L"ScatterGather");
   3.705 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   3.706 +  if (!NT_SUCCESS(status))
   3.707 +  {
   3.708 +    KdPrint(("Could not read ScatterGather value (%08x)\n", status));
   3.709 +    xi->config_sg = 1;
   3.710 +  }
   3.711 +  else
   3.712 +  {
   3.713 +    KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData));
   3.714 +    xi->config_sg = config_param->ParameterData.IntegerData;
   3.715 +  }
   3.716 +  
   3.717 +  NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
   3.718 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   3.719 +  if (!NT_SUCCESS(status))
   3.720 +  {
   3.721 +    KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
   3.722 +    xi->config_gso = 0;
   3.723 +  }
   3.724 +  else
   3.725 +  {
   3.726 +    KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
   3.727 +    xi->config_gso = config_param->ParameterData.IntegerData;
   3.728 +    if (xi->config_gso > 61440)
   3.729 +    {
   3.730 +      xi->config_gso = 61440;
   3.731 +      KdPrint(("(clipped to %d)\n", xi->config_gso));
   3.732 +    }
   3.733 +  }
   3.734 +
   3.735 +  NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
   3.736 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   3.737 +  if (!NT_SUCCESS(status))
   3.738 +  {
   3.739 +    KdPrint(("Could not read ChecksumOffload value (%08x)\n", status));
   3.740 +    xi->config_csum = 1;
   3.741 +  }
   3.742 +  else
   3.743 +  {
   3.744 +    KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData));
   3.745 +    xi->config_csum = !!config_param->ParameterData.IntegerData;
   3.746 +  }
   3.747 +
   3.748 +  NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadRxCheck");
   3.749 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   3.750 +  if (!NT_SUCCESS(status))
   3.751 +  {
   3.752 +    KdPrint(("Could not read ChecksumOffloadRxCheck value (%08x)\n", status));
   3.753 +    xi->config_csum_rx_check = 1;
   3.754 +  }
   3.755 +  else
   3.756 +  {
   3.757 +    KdPrint(("ChecksumOffloadRxCheck = %d\n", config_param->ParameterData.IntegerData));
   3.758 +    xi->config_csum_rx_check = !!config_param->ParameterData.IntegerData;
   3.759 +  }
   3.760 +
   3.761 +  NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadDontFix");
   3.762 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
   3.763 +  if (!NT_SUCCESS(status))
   3.764 +  {
   3.765 +    KdPrint(("Could not read ChecksumOffloadDontFix value (%08x)\n", status));
   3.766 +    xi->config_csum_rx_dont_fix = 0;
   3.767 +  }
   3.768 +  else
   3.769 +  {
   3.770 +    KdPrint(("ChecksumOffloadDontFix = %d\n", config_param->ParameterData.IntegerData));
   3.771 +    xi->config_csum_rx_dont_fix = !!config_param->ParameterData.IntegerData;
   3.772 +  }
   3.773 +  
   3.774 +  
   3.775 +  
   3.776 +  NdisInitUnicodeString(&config_param_name, L"MTU");
   3.777 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);  
   3.778 +  if (!NT_SUCCESS(status))
   3.779 +  {
   3.780 +    KdPrint(("Could not read MTU value (%08x)\n", status));
   3.781 +    xi->config_mtu = 1500;
   3.782 +  }
   3.783 +  else
   3.784 +  {
   3.785 +    KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData));
   3.786 +    xi->config_mtu = config_param->ParameterData.IntegerData;
   3.787 +  }
   3.788 +
   3.789 +  NdisInitUnicodeString(&config_param_name, L"RxInterruptModeration");
   3.790 +  NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);  
   3.791 +  if (!NT_SUCCESS(status))
   3.792 +  {
   3.793 +    KdPrint(("Could not read RxInterruptModeration value (%08x)\n", status));
   3.794 +    xi->config_rx_interrupt_moderation = 1500;
   3.795 +  }
   3.796 +  else
   3.797 +  {
   3.798 +    KdPrint(("RxInterruptModeration = %d\n", config_param->ParameterData.IntegerData));
   3.799 +    xi->config_rx_interrupt_moderation = config_param->ParameterData.IntegerData;
   3.800 +  }
   3.801 +  
   3.802 +
   3.803 +  NdisReadNetworkAddress(&status, &network_address, &network_address_length, config_handle);
   3.804 +  if (!NT_SUCCESS(status) || network_address_length != ETH_ALEN || ((((PUCHAR)network_address)[0] & 0x03) != 0x02))
   3.805 +  {
   3.806 +    KdPrint(("Could not read NetworkAddress value (%08x) or value is invalid\n", status));
   3.807 +    memset(xi->curr_mac_addr, 0, ETH_ALEN);
   3.808 +  }
   3.809 +  else
   3.810 +  {
   3.811 +    memcpy(xi->curr_mac_addr, network_address, ETH_ALEN);
   3.812 +    KdPrint(("     Set MAC address from registry to %02X:%02X:%02X:%02X:%02X:%02X\n",
   3.813 +      xi->curr_mac_addr[0], xi->curr_mac_addr[1], xi->curr_mac_addr[2], 
   3.814 +      xi->curr_mac_addr[3], xi->curr_mac_addr[4], xi->curr_mac_addr[5]));
   3.815 +  }
   3.816 +
   3.817 +  xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE);
   3.818 +  
   3.819 +  NdisCloseConfiguration(config_handle);
   3.820 +
   3.821 +  status = XenNet_D0Entry(xi);
   3.822 +  if (!NT_SUCCESS(status))
   3.823 +  {
   3.824 +    KdPrint(("Failed to go to D0 (%08x)\n", status));
   3.825 +    goto err;
   3.826 +  }
   3.827 +  return NDIS_STATUS_SUCCESS;
   3.828 +  
   3.829 +err:
   3.830 +  NdisFreeMemory(xi, 0, 0);
   3.831 +  *OpenErrorStatus = status;
   3.832 +  FUNCTION_EXIT_STATUS(status);
   3.833 +  return status;
   3.834 +}
   3.835 +
   3.836 +VOID
   3.837 +XenNet_PnPEventNotify(
   3.838 +  IN NDIS_HANDLE MiniportAdapterContext,
   3.839 +  IN NDIS_DEVICE_PNP_EVENT PnPEvent,
   3.840 +  IN PVOID InformationBuffer,
   3.841 +  IN ULONG InformationBufferLength
   3.842 +  )
   3.843 +{
   3.844 +  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   3.845 +  UNREFERENCED_PARAMETER(PnPEvent);
   3.846 +  UNREFERENCED_PARAMETER(InformationBuffer);
   3.847 +  UNREFERENCED_PARAMETER(InformationBufferLength);
   3.848 +
   3.849 +  FUNCTION_ENTER();
   3.850 +  switch (PnPEvent)
   3.851 +  {
   3.852 +  case NdisDevicePnPEventSurpriseRemoved:
   3.853 +    KdPrint((__DRIVER_NAME "     NdisDevicePnPEventSurpriseRemoved\n"));
   3.854 +    break;
   3.855 +  case NdisDevicePnPEventPowerProfileChanged :
   3.856 +    KdPrint((__DRIVER_NAME "     NdisDevicePnPEventPowerProfileChanged\n"));
   3.857 +    break;
   3.858 +  default:
   3.859 +    KdPrint((__DRIVER_NAME "     %d\n", PnPEvent));
   3.860 +    break;
   3.861 +  }
   3.862 +  FUNCTION_EXIT();
   3.863 +}
   3.864 +
   3.865 +/* Called when machine is shutting down, so just quiesce the HW and be done fast. */
   3.866 +VOID
   3.867 +XenNet_Shutdown(
   3.868 +  IN NDIS_HANDLE MiniportAdapterContext
   3.869 +  )
   3.870 +{
   3.871 +  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   3.872 +
   3.873 +  /* remember we are called at >= DIRQL here */
   3.874 +  FUNCTION_ENTER();
   3.875 +  FUNCTION_EXIT();
   3.876 +}
   3.877 +
   3.878 +/* Opposite of XenNet_Init */
   3.879 +VOID
   3.880 +XenNet_Halt(
   3.881 +  IN NDIS_HANDLE MiniportAdapterContext
   3.882 +  )
   3.883 +{
   3.884 +  struct xennet_info *xi = MiniportAdapterContext;
   3.885 +
   3.886 +  FUNCTION_ENTER();
   3.887 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.888 +  
   3.889 +  XenNet_D0Exit(xi);
   3.890 +
   3.891 +  NdisFreeMemory(xi, 0, 0);
   3.892 +
   3.893 +  FUNCTION_EXIT();
   3.894 +}
   3.895 +
   3.896 +NDIS_STATUS
   3.897 +XenNet_D0Exit(struct xennet_info *xi)
   3.898 +{
   3.899 +  FUNCTION_ENTER();
   3.900 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.901 +
   3.902 +  xi->shutting_down = TRUE;
   3.903 +  KeMemoryBarrier(); /* make sure everyone sees that we are now shutting down */
   3.904 +
   3.905 +  XenNet_TxShutdown(xi);
   3.906 +  XenNet_RxShutdown(xi);
   3.907 +
   3.908 +  xi->connected = FALSE;
   3.909 +  KeMemoryBarrier(); /* make sure everyone sees that we are now disconnected */
   3.910 +
   3.911 +  xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
   3.912 +
   3.913 +  FUNCTION_EXIT();
   3.914 +  
   3.915 +  return STATUS_SUCCESS;
   3.916 +}
   3.917 +
   3.918 +NDIS_STATUS 
   3.919 +XenNet_Reset(
   3.920 +  PBOOLEAN  AddressingReset,
   3.921 +  NDIS_HANDLE  MiniportAdapterContext
   3.922 +)
   3.923 +{
   3.924 +  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   3.925 +
   3.926 +  *AddressingReset = FALSE;
   3.927 +  return NDIS_STATUS_SUCCESS;
   3.928 +}
   3.929 +
   3.930 +NTSTATUS
   3.931 +DriverEntry(
   3.932 +  PDRIVER_OBJECT DriverObject,
   3.933 +  PUNICODE_STRING RegistryPath
   3.934 +  )
   3.935 +{
   3.936 +  NTSTATUS status;  
   3.937 +  NDIS_HANDLE ndis_wrapper_handle = NULL;
   3.938 +  NDIS_MINIPORT_CHARACTERISTICS mini_chars;
   3.939 +
   3.940 +  FUNCTION_ENTER();
   3.941 +
   3.942 +  KdPrint((__DRIVER_NAME "     DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
   3.943 +  
   3.944 +  NdisZeroMemory(&mini_chars, sizeof(mini_chars));
   3.945 +
   3.946 +  KdPrint((__DRIVER_NAME "     NdisGetVersion = %x\n", NdisGetVersion()));
   3.947 +
   3.948 +  KdPrint((__DRIVER_NAME "     ndis_wrapper_handle = %p\n", ndis_wrapper_handle));
   3.949 +  NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
   3.950 +  KdPrint((__DRIVER_NAME "     ndis_wrapper_handle = %p\n", ndis_wrapper_handle));
   3.951 +  if (!ndis_wrapper_handle)
   3.952 +  {
   3.953 +    KdPrint((__DRIVER_NAME "     NdisMInitializeWrapper failed\n"));
   3.954 +    return NDIS_STATUS_FAILURE;
   3.955 +  }
   3.956 +  KdPrint((__DRIVER_NAME "     NdisMInitializeWrapper succeeded\n"));
   3.957 +
   3.958 +  /* NDIS 5.1 driver */
   3.959 +  mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
   3.960 +  mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
   3.961 +
   3.962 +  KdPrint((__DRIVER_NAME "     MajorNdisVersion = %d,  MinorNdisVersion = %d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION));
   3.963 +
   3.964 +  mini_chars.HaltHandler = XenNet_Halt;
   3.965 +  mini_chars.InitializeHandler = XenNet_Init;
   3.966 +  //mini_chars.ISRHandler = XenNet_InterruptIsr;
   3.967 +  //mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
   3.968 +  mini_chars.QueryInformationHandler = XenNet_QueryInformation;
   3.969 +  mini_chars.ResetHandler = XenNet_Reset;
   3.970 +  mini_chars.SetInformationHandler = XenNet_SetInformation;
   3.971 +  /* added in v.4 -- use multiple pkts interface */
   3.972 +  mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
   3.973 +  mini_chars.SendPacketsHandler = XenNet_SendPackets;
   3.974 +  /* don't support cancel - no point as packets are never queued for long */
   3.975 +  //mini_chars.CancelSendPacketsHandler = XenNet_CancelSendPackets;
   3.976 +
   3.977 +#ifdef NDIS51_MINIPORT
   3.978 +  /* added in v.5.1 */
   3.979 +  mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
   3.980 +  mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
   3.981 +#else
   3.982 +  // something else here
   3.983 +#endif
   3.984 +
   3.985 +  /* set up upper-edge interface */
   3.986 +  KdPrint((__DRIVER_NAME "     about to call NdisMRegisterMiniport\n"));
   3.987 +  status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
   3.988 +  KdPrint((__DRIVER_NAME "     called NdisMRegisterMiniport\n"));
   3.989 +  if (!NT_SUCCESS(status))
   3.990 +  {
   3.991 +    KdPrint((__DRIVER_NAME "     NdisMRegisterMiniport failed, status = 0x%x\n", status));
   3.992 +    NdisTerminateWrapper(ndis_wrapper_handle, NULL);
   3.993 +    return status;
   3.994 +  }
   3.995 +
   3.996 +  FUNCTION_EXIT();
   3.997 +
   3.998 +  return status;
   3.999 +}
  3.1000 \ No newline at end of file
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xennet/xennet5.h	Sat Apr 30 10:57:23 2011 +1000
     4.3 @@ -0,0 +1,478 @@
     4.4 +/*
     4.5 +PV Drivers for Windows Xen HVM Domains
     4.6 +Copyright (C) 2007 James Harper
     4.7 +Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     4.8 +
     4.9 +This program is free software; you can redistribute it and/or
    4.10 +modify it under the terms of the GNU General Public License
    4.11 +as published by the Free Software Foundation; either version 2
    4.12 +of the License, or (at your option) any later version.
    4.13 +
    4.14 +This program is distributed in the hope that it will be useful,
    4.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.17 +GNU General Public License for more details.
    4.18 +
    4.19 +You should have received a copy of the GNU General Public License
    4.20 +along with this program; if not, write to the Free Software
    4.21 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    4.22 +*/
    4.23 +
    4.24 +#pragma warning(disable: 4201)
    4.25 +#pragma warning(disable: 4214)
    4.26 +
    4.27 +#include <ntddk.h>
    4.28 +#include <wdm.h>
    4.29 +#define NDIS_MINIPORT_DRIVER
    4.30 +#if NTDDI_VERSION < NTDDI_WINXP
    4.31 +# define NDIS50_MINIPORT 1
    4.32 +#else
    4.33 +# define NDIS51_MINIPORT 1
    4.34 +#endif
    4.35 +#include <ndis.h>
    4.36 +#define NTSTRSAFE_LIB
    4.37 +#include <ntstrsafe.h>
    4.38 +#include <liblfds.h>
    4.39 +
    4.40 +#define VENDOR_DRIVER_VERSION_MAJOR 0
    4.41 +#define VENDOR_DRIVER_VERSION_MINOR 10
    4.42 +
    4.43 +#define VENDOR_DRIVER_VERSION (((VENDOR_DRIVER_VERSION_MAJOR) << 16) | (VENDOR_DRIVER_VERSION_MINOR))
    4.44 +
    4.45 +#define __DRIVER_NAME "XenNet"
    4.46 +
    4.47 +#include <xen_windows.h>
    4.48 +#include <memory.h>
    4.49 +#include <grant_table.h>
    4.50 +#include <event_channel.h>
    4.51 +#include <hvm/params.h>
    4.52 +#include <hvm/hvm_op.h>
    4.53 +#include <xen_public.h>
    4.54 +#include <io/ring.h>
    4.55 +#include <io/netif.h>
    4.56 +#include <io/xenbus.h>
    4.57 +#include <stdlib.h>
    4.58 +#define XENNET_POOL_TAG (ULONG) 'XenN'
    4.59 +
    4.60 +/* Xen macros use these, so they need to be redefined to Win equivs */
    4.61 +#define wmb() KeMemoryBarrier()
    4.62 +#define mb() KeMemoryBarrier()
    4.63 +
    4.64 +#define GRANT_INVALID_REF 0
    4.65 +
    4.66 +#define NAME_SIZE 64
    4.67 +
    4.68 +#define ETH_ALEN 6
    4.69 +
    4.70 +/*
    4.71 +#define __NET_USHORT_BYTE_0(x) ((USHORT)(x & 0xFF))
    4.72 +#define __NET_USHORT_BYTE_1(x) ((USHORT)((PUCHAR)&x)[1] & 0xFF)
    4.73 +
    4.74 +#define GET_NET_USHORT(x) ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
    4.75 +#define SET_NET_USHORT(y, x) *((USHORT *)&(y)) = ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
    4.76 +*/
    4.77 +
    4.78 +static FORCEINLINE USHORT
    4.79 +GET_NET_USHORT(USHORT data)
    4.80 +{
    4.81 +  return (data << 8) | (data >> 8);
    4.82 +}
    4.83 +
    4.84 +static FORCEINLINE USHORT
    4.85 +GET_NET_PUSHORT(PVOID pdata)
    4.86 +{
    4.87 +  return (*((PUSHORT)pdata) << 8) | (*((PUSHORT)pdata) >> 8);
    4.88 +}
    4.89 +
    4.90 +static FORCEINLINE VOID
    4.91 +SET_NET_USHORT(PVOID ptr, USHORT data)
    4.92 +{
    4.93 +  *((PUSHORT)ptr) = GET_NET_USHORT(data);
    4.94 +}
    4.95 +
    4.96 +static FORCEINLINE ULONG
    4.97 +GET_NET_ULONG(ULONG data)
    4.98 +{
    4.99 +  ULONG tmp;
   4.100 +  
   4.101 +  tmp = ((data & 0x00ff00ff) << 8) | ((data & 0xff00ff00) >> 8);
   4.102 +  return (tmp << 16) | (tmp >> 16);
   4.103 +}
   4.104 +
   4.105 +static FORCEINLINE ULONG
   4.106 +GET_NET_PULONG(PVOID pdata)
   4.107 +{
   4.108 +  ULONG tmp;
   4.109 +  
   4.110 +  tmp = ((*((PULONG)pdata) & 0x00ff00ff) << 8) | ((*((PULONG)pdata) & 0xff00ff00) >> 8);
   4.111 +  return (tmp << 16) | (tmp >> 16);
   4.112 +}
   4.113 +
   4.114 +static FORCEINLINE VOID
   4.115 +SET_NET_ULONG(PVOID ptr, ULONG data)
   4.116 +{
   4.117 +  *((PULONG)ptr) = GET_NET_ULONG(data);
   4.118 +}
   4.119 +/*
   4.120 +#define GET_NET_ULONG(x) ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
   4.121 +#define SET_NET_ULONG(y, x) *((ULONG *)&(y)) = ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
   4.122 +*/
   4.123 +
   4.124 +#define SUPPORTED_PACKET_FILTERS (\
   4.125 +  NDIS_PACKET_TYPE_DIRECTED | \
   4.126 +  NDIS_PACKET_TYPE_MULTICAST | \
   4.127 +  NDIS_PACKET_TYPE_BROADCAST | \
   4.128 +  NDIS_PACKET_TYPE_PROMISCUOUS | \
   4.129 +  NDIS_PACKET_TYPE_ALL_MULTICAST)
   4.130 +
   4.131 +/* couldn't get regular xen ring macros to work...*/
   4.132 +#define __NET_RING_SIZE(type, _sz) \
   4.133 +    (__RD32( \
   4.134 +    (_sz - sizeof(struct type##_sring) + sizeof(union type##_sring_entry)) \
   4.135 +    / sizeof(union type##_sring_entry)))
   4.136 +
   4.137 +#define NET_TX_RING_SIZE __NET_RING_SIZE(netif_tx, PAGE_SIZE)
   4.138 +#define NET_RX_RING_SIZE __NET_RING_SIZE(netif_rx, PAGE_SIZE)
   4.139 +
   4.140 +#pragma warning(disable: 4127) // conditional expression is constant
   4.141 +
   4.142 +#define MIN_LARGE_SEND_SEGMENTS 4
   4.143 +
   4.144 +/* TODO: crank this up if we support higher mtus? */
   4.145 +#define XN_HDR_SIZE 14
   4.146 +#define XN_MAX_DATA_SIZE 1500
   4.147 +#define XN_MIN_FRAME_SIZE 60
   4.148 +#define XN_MAX_FRAME_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
   4.149 +/*
   4.150 +#if !defined(OFFLOAD_LARGE_SEND)
   4.151 +  #define XN_MAX_PKT_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
   4.152 +#else
   4.153 +  #define XN_MAX_PKT_SIZE MAX_LARGE_SEND_OFFLOAD
   4.154 +#endif
   4.155 +*/
   4.156 +
   4.157 +#define XN_MAX_SEND_PKTS 16
   4.158 +
   4.159 +#define XENSOURCE_MAC_HDR 0x00163E
   4.160 +#define XN_VENDOR_DESC "Xensource"
   4.161 +#define MAX_XENBUS_STR_LEN 128
   4.162 +
   4.163 +#define RX_MIN_TARGET 8
   4.164 +#define RX_DFL_MIN_TARGET 256
   4.165 +#define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
   4.166 +
   4.167 +//#define MAX_BUFFERS_PER_PACKET NET_RX_RING_SIZE
   4.168 +
   4.169 +#define MIN_ETH_HEADER_LENGTH 14
   4.170 +#define MAX_ETH_HEADER_LENGTH 14
   4.171 +#define MIN_IP4_HEADER_LENGTH 20
   4.172 +#define MAX_IP4_HEADER_LENGTH (15 * 4)
   4.173 +#define MIN_TCP_HEADER_LENGTH 20
   4.174 +#define MAX_TCP_HEADER_LENGTH (15 * 4)
   4.175 +#define MAX_PKT_HEADER_LENGTH (MAX_ETH_HEADER_LENGTH + MAX_IP4_HEADER_LENGTH + MAX_TCP_HEADER_LENGTH)
   4.176 +
   4.177 +#define MIN_LOOKAHEAD_LENGTH (MAX_IP4_HEADER_LENGTH + MAX_TCP_HEADER_LENGTH)
   4.178 +#define MAX_LOOKAHEAD_LENGTH 256
   4.179 +
   4.180 +#define LINUX_MAX_SG_ELEMENTS 19
   4.181 +
   4.182 +struct _shared_buffer_t;
   4.183 +
   4.184 +typedef struct _shared_buffer_t shared_buffer_t;
   4.185 +
   4.186 +struct _shared_buffer_t
   4.187 +{
   4.188 +  struct netif_rx_response rsp;
   4.189 +  shared_buffer_t *next;
   4.190 +  grant_ref_t gref;
   4.191 +  USHORT offset;
   4.192 +  PVOID virtual;
   4.193 +  PNDIS_BUFFER buffer;
   4.194 +  //USHORT id;
   4.195 +  volatile LONG ref_count;
   4.196 +};
   4.197 +
   4.198 +typedef struct
   4.199 +{
   4.200 +  PNDIS_PACKET packet; /* only set on the last packet */
   4.201 +  PVOID *cb;
   4.202 +  grant_ref_t gref;
   4.203 +} tx_shadow_t;
   4.204 +
   4.205 +typedef struct {
   4.206 +  PNDIS_BUFFER first_buffer;
   4.207 +  PNDIS_BUFFER curr_buffer;
   4.208 +  shared_buffer_t *first_pb;
   4.209 +  shared_buffer_t *curr_pb;
   4.210 +  PUCHAR first_buffer_virtual;
   4.211 +  ULONG mdl_count;
   4.212 +  ULONG curr_mdl_offset;
   4.213 +  USHORT mss;
   4.214 +  NDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   4.215 +  BOOLEAN csum_blank;
   4.216 +  BOOLEAN data_validated;
   4.217 +  BOOLEAN split_required;
   4.218 +  UCHAR ip_version;
   4.219 +  PUCHAR header;
   4.220 +  ULONG first_buffer_length;
   4.221 +  ULONG header_length;
   4.222 +  UCHAR ip_proto;
   4.223 +  ULONG total_length;
   4.224 +  USHORT ip4_header_length;
   4.225 +  USHORT ip4_length;
   4.226 +  USHORT tcp_header_length;
   4.227 +  BOOLEAN tcp_has_options;
   4.228 +  USHORT tcp_length;
   4.229 +  USHORT tcp_remaining;
   4.230 +  ULONG tcp_seq;
   4.231 +  /* anything past here doesn't get cleared automatically by the ClearPacketInfo */
   4.232 +  UCHAR header_data[MAX_LOOKAHEAD_LENGTH + MAX_ETH_HEADER_LENGTH];
   4.233 +} packet_info_t;
   4.234 +
   4.235 +#define PAGE_LIST_SIZE (max(NET_RX_RING_SIZE, NET_TX_RING_SIZE) * 4)
   4.236 +#define MULTICAST_LIST_MAX_SIZE 32
   4.237 +
   4.238 +struct xennet_info
   4.239 +{
   4.240 +  BOOLEAN inactive;
   4.241 +  
   4.242 +  /* Base device vars */
   4.243 +  PDEVICE_OBJECT pdo;
   4.244 +  PDEVICE_OBJECT fdo;
   4.245 +  PDEVICE_OBJECT lower_do;
   4.246 +  //WDFDEVICE wdf_device;
   4.247 +  WCHAR dev_desc[NAME_SIZE];
   4.248 +
   4.249 +  /* NDIS-related vars */
   4.250 +  NDIS_HANDLE adapter_handle;
   4.251 +  NDIS_MINIPORT_INTERRUPT interrupt;
   4.252 +  ULONG packet_filter;
   4.253 +  BOOLEAN connected;
   4.254 +  BOOLEAN shutting_down;
   4.255 +  BOOLEAN tx_shutting_down;
   4.256 +  BOOLEAN rx_shutting_down;
   4.257 +  uint8_t perm_mac_addr[ETH_ALEN];
   4.258 +  uint8_t curr_mac_addr[ETH_ALEN];
   4.259 +  ULONG current_lookahead;
   4.260 +  NDIS_DEVICE_POWER_STATE new_power_state;
   4.261 +  NDIS_DEVICE_POWER_STATE power_state;
   4.262 +  PIO_WORKITEM power_workitem;
   4.263 +
   4.264 +  /* Misc. Xen vars */
   4.265 +  XENPCI_VECTORS vectors;
   4.266 +  PXENPCI_DEVICE_STATE device_state;
   4.267 +  evtchn_port_t event_channel;
   4.268 +  ULONG state;
   4.269 +  char backend_path[MAX_XENBUS_STR_LEN];
   4.270 +  ULONG backend_state;
   4.271 +  PVOID config_page;
   4.272 +  UCHAR multicast_list[MULTICAST_LIST_MAX_SIZE][6];
   4.273 +  ULONG multicast_list_size;
   4.274 +  KDPC suspend_dpc;
   4.275 +  PIO_WORKITEM resume_work_item;
   4.276 +  KSPIN_LOCK resume_lock;
   4.277 +  KDPC rxtx_dpc;
   4.278 +
   4.279 +  /* tx related - protected by tx_lock */
   4.280 +  KSPIN_LOCK tx_lock;
   4.281 +  LIST_ENTRY tx_waiting_pkt_list;
   4.282 +  struct netif_tx_front_ring tx;
   4.283 +  ULONG tx_ring_free;
   4.284 +  tx_shadow_t tx_shadows[NET_TX_RING_SIZE];
   4.285 +  NDIS_HANDLE tx_buffer_pool;
   4.286 +#define TX_HEADER_BUFFER_SIZE 512
   4.287 +//#define TX_COALESCE_BUFFERS (NET_TX_RING_SIZE >> 2)
   4.288 +#define TX_COALESCE_BUFFERS (NET_TX_RING_SIZE)
   4.289 +  KEVENT tx_idle_event;
   4.290 +  ULONG tx_outstanding;
   4.291 +  ULONG tx_id_free;
   4.292 +  USHORT tx_id_list[NET_TX_RING_SIZE];
   4.293 +  NPAGED_LOOKASIDE_LIST tx_lookaside_list;
   4.294 +
   4.295 +  /* rx_related - protected by rx_lock */
   4.296 +  KSPIN_LOCK rx_lock;
   4.297 +  struct netif_rx_front_ring rx;
   4.298 +  ULONG rx_id_free;
   4.299 +  packet_info_t *rxpi;
   4.300 +  KEVENT packet_returned_event;
   4.301 +  //NDIS_MINIPORT_TIMER rx_timer;
   4.302 +  KTIMER rx_timer;
   4.303 +  KDPC rx_timer_dpc;
   4.304 +  NDIS_HANDLE rx_packet_pool;
   4.305 +  NDIS_HANDLE rx_buffer_pool;
   4.306 +  volatile LONG rx_pb_free;
   4.307 +  struct stack_state *rx_packet_stack;
   4.308 +  struct stack_state *rx_pb_stack;
   4.309 +  shared_buffer_t *rx_ring_pbs[NET_RX_RING_SIZE];
   4.310 +  NPAGED_LOOKASIDE_LIST rx_lookaside_list;
   4.311 +  /* Receive-ring batched refills. */
   4.312 +  ULONG rx_target;
   4.313 +  ULONG rx_max_target;
   4.314 +  ULONG rx_min_target;
   4.315 +  shared_buffer_t *rx_partial_buf;
   4.316 +  BOOLEAN rx_partial_extra_info_flag ;
   4.317 +  BOOLEAN rx_partial_more_data_flag;
   4.318 +
   4.319 +  /* how many packets are in the net stack atm */
   4.320 +  LONG rx_outstanding;
   4.321 +
   4.322 +  /* config vars from registry */
   4.323 +  ULONG config_sg;
   4.324 +  ULONG config_csum;
   4.325 +  ULONG config_csum_rx_check;
   4.326 +  ULONG config_csum_rx_dont_fix;
   4.327 +  ULONG config_gso;
   4.328 +  ULONG config_mtu;
   4.329 +  ULONG config_rx_interrupt_moderation;
   4.330 +
   4.331 +  NDIS_TASK_TCP_IP_CHECKSUM setting_csum;
   4.332 +  ULONG setting_max_offload;
   4.333 +
   4.334 +  /* config stuff calculated from the above */
   4.335 +  ULONG config_max_pkt_size;
   4.336 +
   4.337 +  /* stats */
   4.338 +  ULONG64 stat_tx_ok;
   4.339 +  ULONG64 stat_rx_ok;
   4.340 +  ULONG64 stat_tx_error;
   4.341 +  ULONG64 stat_rx_error;
   4.342 +  ULONG64 stat_rx_no_buffer;
   4.343 +  
   4.344 +} typedef xennet_info_t;
   4.345 +
   4.346 +VOID
   4.347 +XenNet_ReturnPacket(
   4.348 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.349 +  IN PNDIS_PACKET Packet
   4.350 +  );
   4.351 +
   4.352 +BOOLEAN
   4.353 +XenNet_RxInit(xennet_info_t *xi);
   4.354 +
   4.355 +BOOLEAN
   4.356 +XenNet_RxShutdown(xennet_info_t *xi);
   4.357 +
   4.358 +VOID
   4.359 +XenNet_RxResumeStart(xennet_info_t *xi);
   4.360 +
   4.361 +VOID
   4.362 +XenNet_RxResumeEnd(xennet_info_t *xi);
   4.363 +
   4.364 +BOOLEAN
   4.365 +XenNet_RxBufferCheck(struct xennet_info *xi);
   4.366 +
   4.367 +VOID
   4.368 +XenNet_TxResumeStart(xennet_info_t *xi);
   4.369 +
   4.370 +VOID
   4.371 +XenNet_TxResumeEnd(xennet_info_t *xi);
   4.372 +
   4.373 +VOID
   4.374 +XenNet_SendPackets(
   4.375 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.376 +  IN PPNDIS_PACKET PacketArray,
   4.377 +  IN UINT NumberOfPackets
   4.378 +  );
   4.379 +
   4.380 +VOID
   4.381 +XenNet_CancelSendPackets(
   4.382 +  NDIS_HANDLE MiniportAdapterContext,
   4.383 +  PVOID CancelId);
   4.384 +  
   4.385 +BOOLEAN
   4.386 +XenNet_TxInit(xennet_info_t *xi);
   4.387 +
   4.388 +BOOLEAN
   4.389 +XenNet_TxShutdown(xennet_info_t *xi);
   4.390 +
   4.391 +VOID
   4.392 +XenNet_TxBufferGC(struct xennet_info *xi, BOOLEAN dont_set_event);
   4.393 +
   4.394 +NDIS_STATUS
   4.395 +XenNet_QueryInformation(
   4.396 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.397 +  IN NDIS_OID Oid,
   4.398 +  IN PVOID InformationBuffer,
   4.399 +  IN ULONG InformationBufferLength,
   4.400 +  OUT PULONG BytesWritten,
   4.401 +  OUT PULONG BytesNeeded);
   4.402 +
   4.403 +NDIS_STATUS
   4.404 +XenNet_SetInformation(
   4.405 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.406 +  IN NDIS_OID Oid,
   4.407 +  IN PVOID InformationBuffer,
   4.408 +  IN ULONG InformationBufferLength,
   4.409 +  OUT PULONG BytesRead,
   4.410 +  OUT PULONG BytesNeeded
   4.411 +  );
   4.412 +
   4.413 +NDIS_STATUS
   4.414 +XenNet_D0Entry(struct xennet_info *xi);
   4.415 +NDIS_STATUS
   4.416 +XenNet_D0Exit(struct xennet_info *xi);
   4.417 +IO_WORKITEM_ROUTINE
   4.418 +XenNet_SetPower;
   4.419 +
   4.420 +/* return values */
   4.421 +#define PARSE_OK 0
   4.422 +#define PARSE_TOO_SMALL 1 /* first buffer is too small */
   4.423 +#define PARSE_UNKNOWN_TYPE 2
   4.424 +
   4.425 +BOOLEAN
   4.426 +XenNet_BuildHeader(packet_info_t *pi, PVOID header, ULONG new_header_size);
   4.427 +ULONG
   4.428 +XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR buffer, ULONG min_header_size);
   4.429 +BOOLEAN
   4.430 +XenNet_FilterAcceptPacket(struct xennet_info *xi,packet_info_t *pi);
   4.431 +
   4.432 +VOID
   4.433 +XenNet_SumIpHeader(
   4.434 +  PUCHAR header,
   4.435 +  USHORT ip4_header_length
   4.436 +);
   4.437 +
   4.438 +static __forceinline VOID
   4.439 +XenNet_ClearPacketInfo(packet_info_t *pi)
   4.440 +{
   4.441 +#if 1
   4.442 +  RtlZeroMemory(pi, sizeof(packet_info_t) - FIELD_OFFSET(packet_info_t, header_data));
   4.443 +#else
   4.444 +  pi->mdl_count = 0;
   4.445 +  pi->mss = 0;
   4.446 +  pi->ip4_header_length = 0;
   4.447 +  pi->tcp_header_length = 0;
   4.448 +  pi->curr_mdl_index = pi->curr_mdl_offset = 0;
   4.449 +  pi->extra_info = pi->more_frags = pi->csum_blank =
   4.450 +    pi->data_validated = pi->split_required = 0;
   4.451 +#endif
   4.452 +}
   4.453 +
   4.454 +/* Get some data from the current packet, but don't cross a page boundry. */
   4.455 +static __forceinline ULONG
   4.456 +XenNet_QueryData(packet_info_t *pi, ULONG length)
   4.457 +{
   4.458 +  ULONG offset_in_page;
   4.459 +  
   4.460 +  if (length > MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset)
   4.461 +    length = MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset;
   4.462 +
   4.463 +  offset_in_page = (MmGetMdlByteOffset(pi->curr_buffer) + pi->curr_mdl_offset) & (PAGE_SIZE - 1);
   4.464 +  if (offset_in_page + length > PAGE_SIZE)
   4.465 +    length = PAGE_SIZE - offset_in_page;
   4.466 +  
   4.467 +  return length;
   4.468 +}
   4.469 +
   4.470 +/* Move the pointers forward by the given amount. No error checking is done.  */
   4.471 +static __forceinline VOID
   4.472 +XenNet_EatData(packet_info_t *pi, ULONG length)
   4.473 +{
   4.474 +  pi->curr_mdl_offset += length;
   4.475 +  if (pi->curr_mdl_offset >= MmGetMdlByteCount(pi->curr_buffer))
   4.476 +  {
   4.477 +    pi->curr_mdl_offset -= MmGetMdlByteCount(pi->curr_buffer);
   4.478 +    NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
   4.479 +  }
   4.480 +}
   4.481 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xennet/xennet5_common.c	Sat Apr 30 10:57:23 2011 +1000
     5.3 @@ -0,0 +1,286 @@
     5.4 +/*
     5.5 +PV Net Driver for Windows Xen HVM Domains
     5.6 +Copyright (C) 2007 James Harper
     5.7 +Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     5.8 +
     5.9 +This program is free software; you can redistribute it and/or
    5.10 +modify it under the terms of the GNU General Public License
    5.11 +as published by the Free Software Foundation; either version 2
    5.12 +of the License, or (at your option) any later version.
    5.13 +
    5.14 +This program is distributed in the hope that it will be useful,
    5.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.17 +GNU General Public License for more details.
    5.18 +
    5.19 +You should have received a copy of the GNU General Public License
    5.20 +along with this program; if not, write to the Free Software
    5.21 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    5.22 +*/
    5.23 +
    5.24 +#include "xennet5.h"
    5.25 +
    5.26 +/* Increase the header to a certain size */
    5.27 +BOOLEAN
    5.28 +XenNet_BuildHeader(packet_info_t *pi, PUCHAR header, ULONG new_header_size)
    5.29 +{
    5.30 +  ULONG bytes_remaining;
    5.31 +
    5.32 +  //FUNCTION_ENTER();
    5.33 +
    5.34 +  if (!header)
    5.35 +    header = pi->header;
    5.36 +
    5.37 +  if (new_header_size <= pi->header_length)
    5.38 +  {
    5.39 +    return TRUE; /* header is already at least the required size */
    5.40 +  }
    5.41 +
    5.42 +  if (header == pi->first_buffer_virtual)
    5.43 +  {
    5.44 +    /* still working in the first buffer */
    5.45 +    if (new_header_size <= pi->first_buffer_length)
    5.46 +    {
    5.47 +      //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " new_header_size <= pi->first_buffer_length\n"));
    5.48 +      pi->header_length = new_header_size;
    5.49 +      if (pi->header_length == pi->first_buffer_length)
    5.50 +      {
    5.51 +        NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
    5.52 +        pi->curr_mdl_offset = 0;
    5.53 +        if (pi->curr_pb)
    5.54 +          pi->curr_pb = pi->curr_pb->next;
    5.55 +      }
    5.56 +      else
    5.57 +      {
    5.58 +        pi->curr_mdl_offset = (USHORT)new_header_size;
    5.59 +      }      
    5.60 +      return TRUE;
    5.61 +    }
    5.62 +    else
    5.63 +    {
    5.64 +      //KdPrint((__DRIVER_NAME "     Switching to header_data\n"));
    5.65 +      memcpy(pi->header_data, header, pi->header_length);
    5.66 +      header = pi->header = pi->header_data;
    5.67 +    }
    5.68 +  }
    5.69 +  
    5.70 +  bytes_remaining = new_header_size - pi->header_length;
    5.71 +  // TODO: if there are only a small number of bytes left in the current buffer then increase to consume that too... it would have to be no more than the size of header+mss though
    5.72 +
    5.73 +  //KdPrint((__DRIVER_NAME "     A bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
    5.74 +  while (bytes_remaining && pi->curr_buffer)
    5.75 +  {
    5.76 +    ULONG copy_size;
    5.77 +    
    5.78 +    ASSERT(pi->curr_buffer);
    5.79 +    //KdPrint((__DRIVER_NAME "     B bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
    5.80 +    if (MmGetMdlByteCount(pi->curr_buffer))
    5.81 +    {
    5.82 +      PUCHAR src_addr;
    5.83 +      src_addr = MmGetSystemAddressForMdlSafe(pi->curr_buffer, NormalPagePriority);
    5.84 +      if (!src_addr)
    5.85 +        return FALSE;
    5.86 +      copy_size = min(bytes_remaining, MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset);
    5.87 +      //KdPrint((__DRIVER_NAME "     B copy_size = %d\n", copy_size));
    5.88 +      memcpy(header + pi->header_length,
    5.89 +        src_addr + pi->curr_mdl_offset, copy_size);
    5.90 +      pi->curr_mdl_offset = (USHORT)(pi->curr_mdl_offset + copy_size);
    5.91 +      pi->header_length += copy_size;
    5.92 +      bytes_remaining -= copy_size;
    5.93 +    }
    5.94 +    if (pi->curr_mdl_offset == MmGetMdlByteCount(pi->curr_buffer))
    5.95 +    {
    5.96 +      NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
    5.97 +      if (pi->curr_pb)
    5.98 +        pi->curr_pb = pi->curr_pb->next;
    5.99 +      pi->curr_mdl_offset = 0;
   5.100 +    }
   5.101 +  }
   5.102 +  //KdPrint((__DRIVER_NAME "     C bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
   5.103 +  if (bytes_remaining)
   5.104 +  {
   5.105 +    //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " bytes_remaining\n"));
   5.106 +    return FALSE;
   5.107 +  }
   5.108 +  //FUNCTION_EXIT();
   5.109 +  return TRUE;
   5.110 +}
   5.111 +
   5.112 +ULONG
   5.113 +XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR alt_buffer, ULONG min_header_size)
   5.114 +{
   5.115 +  //FUNCTION_ENTER();
   5.116 +
   5.117 +  ASSERT(pi->first_buffer);
   5.118 +  
   5.119 +  NdisQueryBufferSafe(pi->first_buffer, (PVOID)&pi->first_buffer_virtual, &pi->first_buffer_length, NormalPagePriority);
   5.120 +  pi->curr_buffer = pi->first_buffer;
   5.121 +  if (alt_buffer)
   5.122 +    pi->header = alt_buffer;
   5.123 +  else
   5.124 +    pi->header = pi->first_buffer_virtual;
   5.125 +
   5.126 +  pi->header_length = 0;
   5.127 +  pi->curr_mdl_offset = 0;
   5.128 +
   5.129 +  XenNet_BuildHeader(pi, NULL, min_header_size);
   5.130 +  
   5.131 +  if (!XenNet_BuildHeader(pi, NULL, (ULONG)XN_HDR_SIZE))
   5.132 +  {
   5.133 +    KdPrint((__DRIVER_NAME "     packet too small (Ethernet Header)\n"));
   5.134 +    return PARSE_TOO_SMALL;
   5.135 +  }
   5.136 +
   5.137 +  switch (GET_NET_PUSHORT(&pi->header[12])) // L2 protocol field
   5.138 +  {
   5.139 +  case 0x0800:
   5.140 +    //KdPrint((__DRIVER_NAME "     IP\n"));
   5.141 +    if (pi->header_length < (ULONG)(XN_HDR_SIZE + 20))
   5.142 +    {
   5.143 +      if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + 20)))
   5.144 +      {
   5.145 +        KdPrint((__DRIVER_NAME "     packet too small (IP Header)\n"));
   5.146 +        return PARSE_TOO_SMALL;
   5.147 +      }
   5.148 +    }
   5.149 +    pi->ip_version = (pi->header[XN_HDR_SIZE + 0] & 0xF0) >> 4;
   5.150 +    if (pi->ip_version != 4)
   5.151 +    {
   5.152 +      KdPrint((__DRIVER_NAME "     ip_version = %d\n", pi->ip_version));
   5.153 +      return PARSE_UNKNOWN_TYPE;
   5.154 +    }
   5.155 +    pi->ip4_header_length = (pi->header[XN_HDR_SIZE + 0] & 0x0F) << 2;
   5.156 +    if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20))
   5.157 +    {
   5.158 +      if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)))
   5.159 +      {
   5.160 +        //KdPrint((__DRIVER_NAME "     packet too small (IP Header + IP Options + TCP Header)\n"));
   5.161 +        return PARSE_TOO_SMALL;
   5.162 +      }
   5.163 +    }
   5.164 +    break;
   5.165 +  default:
   5.166 +    //KdPrint((__DRIVER_NAME "     Not IP (%d)\n", GET_NET_PUSHORT(&pi->header[12])));
   5.167 +    return PARSE_UNKNOWN_TYPE;
   5.168 +  }
   5.169 +  pi->ip_proto = pi->header[XN_HDR_SIZE + 9];
   5.170 +  switch (pi->ip_proto)
   5.171 +  {
   5.172 +  case 6:  // TCP
   5.173 +  case 17: // UDP
   5.174 +    break;
   5.175 +  default:
   5.176 +    //KdPrint((__DRIVER_NAME "     Not TCP/UDP (%d)\n", pi->ip_proto));
   5.177 +    return PARSE_UNKNOWN_TYPE;
   5.178 +  }
   5.179 +  pi->ip4_length = GET_NET_PUSHORT(&pi->header[XN_HDR_SIZE + 2]);
   5.180 +  pi->tcp_header_length = (pi->header[XN_HDR_SIZE + pi->ip4_header_length + 12] & 0xf0) >> 2;
   5.181 +
   5.182 +  if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length))
   5.183 +  {
   5.184 +    if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length)))
   5.185 +    {
   5.186 +      //KdPrint((__DRIVER_NAME "     packet too small (IP Header + IP Options + TCP Header + TCP Options)\n"));
   5.187 +      return PARSE_TOO_SMALL;
   5.188 +    }
   5.189 +  }
   5.190 +  
   5.191 +  if ((ULONG)XN_HDR_SIZE + pi->ip4_length > pi->total_length)
   5.192 +  {
   5.193 +    KdPrint((__DRIVER_NAME "     XN_HDR_SIZE + ip4_length (%d) > total_length (%d)\n", XN_HDR_SIZE + pi->ip4_length, pi->total_length));
   5.194 +    return PARSE_UNKNOWN_TYPE;
   5.195 +  }
   5.196 +
   5.197 +  pi->tcp_length = pi->ip4_length - pi->ip4_header_length - pi->tcp_header_length;
   5.198 +  pi->tcp_remaining = pi->tcp_length;
   5.199 +  pi->tcp_seq = GET_NET_PULONG(&pi->header[XN_HDR_SIZE + pi->ip4_header_length + 4]);
   5.200 +  pi->tcp_has_options = (BOOLEAN)(pi->tcp_header_length > 20);
   5.201 +  if (pi->mss > 0 && pi->tcp_length > pi->mss)
   5.202 +    pi->split_required = TRUE;
   5.203 +
   5.204 +  //KdPrint((__DRIVER_NAME "     ip4_length = %d\n", pi->ip4_length));
   5.205 +  //KdPrint((__DRIVER_NAME "     tcp_length = %d\n", pi->tcp_length));
   5.206 +  //FUNCTION_EXIT();
   5.207 +  
   5.208 +  return PARSE_OK;
   5.209 +}
   5.210 +
   5.211 +VOID
   5.212 +XenNet_SumIpHeader(
   5.213 +  PUCHAR header,
   5.214 +  USHORT ip4_header_length
   5.215 +)
   5.216 +{
   5.217 +  ULONG csum = 0;
   5.218 +  USHORT i;
   5.219 +
   5.220 +  ASSERT(ip4_header_length > 12);
   5.221 +  ASSERT(!(ip4_header_length & 1));
   5.222 +
   5.223 +  header[XN_HDR_SIZE + 10] = 0;
   5.224 +  header[XN_HDR_SIZE + 11] = 0;
   5.225 +  for (i = 0; i < ip4_header_length; i += 2)
   5.226 +  {
   5.227 +    csum += GET_NET_PUSHORT(&header[XN_HDR_SIZE + i]);
   5.228 +  }
   5.229 +  while (csum & 0xFFFF0000)
   5.230 +    csum = (csum & 0xFFFF) + (csum >> 16);
   5.231 +  csum = ~csum;
   5.232 +  SET_NET_USHORT(&header[XN_HDR_SIZE + 10], (USHORT)csum);
   5.233 +}
   5.234 +
   5.235 +BOOLEAN
   5.236 +XenNet_FilterAcceptPacket(struct xennet_info *xi,packet_info_t *pi)
   5.237 +{
   5.238 +  BOOLEAN is_multicast = FALSE;
   5.239 +  BOOLEAN is_my_multicast = FALSE;
   5.240 +  BOOLEAN is_broadcast = FALSE;
   5.241 +  BOOLEAN is_directed = FALSE;
   5.242 +  ULONG i;
   5.243 +
   5.244 +  if (pi->header[0] == 0xFF && pi->header[1] == 0xFF
   5.245 +      && pi->header[2] == 0xFF && pi->header[3] == 0xFF
   5.246 +      && pi->header[4] == 0xFF && pi->header[5] == 0xFF)
   5.247 +  {
   5.248 +    is_broadcast = TRUE;
   5.249 +  }
   5.250 +  else if (pi->header[0] & 0x01)
   5.251 +  {
   5.252 +    is_multicast = TRUE;
   5.253 +    for (i = 0; i < xi->multicast_list_size; i++)
   5.254 +    {
   5.255 +      if (memcmp(xi->multicast_list[i], pi->header, 6) == 0)
   5.256 +        break;
   5.257 +    }
   5.258 +    if (i < xi->multicast_list_size)
   5.259 +    {
   5.260 +      is_my_multicast = TRUE;
   5.261 +    }    
   5.262 +  }
   5.263 +  if (memcmp(xi->curr_mac_addr, pi->header, ETH_ALEN) == 0)
   5.264 +  {
   5.265 +    is_directed = TRUE;
   5.266 +  }
   5.267 +
   5.268 +  if (is_directed && (xi->packet_filter & NDIS_PACKET_TYPE_DIRECTED))
   5.269 +  {
   5.270 +    return TRUE;
   5.271 +  }  
   5.272 +  if (is_my_multicast && (xi->packet_filter & NDIS_PACKET_TYPE_MULTICAST))
   5.273 +  {
   5.274 +    return TRUE;
   5.275 +  }
   5.276 +  if (is_multicast && (xi->packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST))
   5.277 +  {
   5.278 +    return TRUE;
   5.279 +  }
   5.280 +  if (is_broadcast && (xi->packet_filter & NDIS_PACKET_TYPE_BROADCAST))
   5.281 +  {
   5.282 +    return TRUE;
   5.283 +  }
   5.284 +  if (xi->packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS)
   5.285 +  {
   5.286 +    return TRUE;
   5.287 +  }
   5.288 +  return FALSE;
   5.289 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xennet/xennet5_oid.c	Sat Apr 30 10:57:23 2011 +1000
     6.3 @@ -0,0 +1,772 @@
     6.4 +/*
     6.5 +PV Net Driver for Windows Xen HVM Domains
     6.6 +Copyright (C) 2007 James Harper
     6.7 +Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     6.8 +
     6.9 +This program is free software; you can redistribute it and/or
    6.10 +modify it under the terms of the GNU General Public License
    6.11 +as published by the Free Software Foundation; either version 2
    6.12 +of the License, or (at your option) any later version.
    6.13 +
    6.14 +This program is distributed in the hope that it will be useful,
    6.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.17 +GNU General Public License for more details.
    6.18 +
    6.19 +You should have received a copy of the GNU General Public License
    6.20 +along with this program; if not, write to the Free Software
    6.21 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    6.22 +*/
    6.23 +
    6.24 +#include "xennet5.h"
    6.25 +
    6.26 +// Q = Query Mandatory, S = Set Mandatory
    6.27 +NDIS_OID supported_oids[] =
    6.28 +{
    6.29 +  /* general OIDs */
    6.30 +  OID_GEN_SUPPORTED_LIST,        // Q
    6.31 +  OID_GEN_HARDWARE_STATUS,       // Q
    6.32 +  OID_GEN_MEDIA_SUPPORTED,       // Q
    6.33 +  OID_GEN_MEDIA_IN_USE,          // Q
    6.34 +  OID_GEN_MAXIMUM_LOOKAHEAD,     // Q
    6.35 +  OID_GEN_MAXIMUM_FRAME_SIZE,    // Q
    6.36 +  OID_GEN_LINK_SPEED,            // Q
    6.37 +  OID_GEN_TRANSMIT_BUFFER_SPACE, // Q
    6.38 +  OID_GEN_RECEIVE_BUFFER_SPACE,  // Q
    6.39 +  OID_GEN_TRANSMIT_BLOCK_SIZE,   // Q
    6.40 +  OID_GEN_RECEIVE_BLOCK_SIZE,    // Q
    6.41 +  OID_GEN_VENDOR_ID,             // Q
    6.42 +  OID_GEN_VENDOR_DESCRIPTION,    // Q
    6.43 +  OID_GEN_CURRENT_PACKET_FILTER, // QS
    6.44 +  OID_GEN_CURRENT_LOOKAHEAD,     // QS
    6.45 +  OID_GEN_DRIVER_VERSION,        // Q
    6.46 +  OID_GEN_VENDOR_DRIVER_VERSION, // Q
    6.47 +  OID_GEN_MAXIMUM_TOTAL_SIZE,    // Q
    6.48 +  OID_GEN_PROTOCOL_OPTIONS,      // S
    6.49 +  OID_GEN_MAC_OPTIONS,           // Q
    6.50 +  OID_GEN_MEDIA_CONNECT_STATUS,  // Q
    6.51 +  OID_GEN_MAXIMUM_SEND_PACKETS,  // Q
    6.52 +  /* stats */
    6.53 +  OID_GEN_XMIT_OK,               // Q
    6.54 +  OID_GEN_RCV_OK,                // Q
    6.55 +  OID_GEN_XMIT_ERROR,            // Q
    6.56 +  OID_GEN_RCV_ERROR,             // Q
    6.57 +  OID_GEN_RCV_NO_BUFFER,         // Q
    6.58 +  /* media-specific OIDs */
    6.59 +  OID_802_3_PERMANENT_ADDRESS,
    6.60 +  OID_802_3_CURRENT_ADDRESS,
    6.61 +  OID_802_3_MULTICAST_LIST,
    6.62 +  OID_802_3_MAXIMUM_LIST_SIZE,
    6.63 +  OID_802_3_RCV_ERROR_ALIGNMENT,
    6.64 +  OID_802_3_XMIT_ONE_COLLISION,
    6.65 +  OID_802_3_XMIT_MORE_COLLISIONS,
    6.66 +  /* tcp offload */
    6.67 +  OID_TCP_TASK_OFFLOAD,
    6.68 +  /* power */
    6.69 +  OID_PNP_CAPABILITIES,
    6.70 +  OID_PNP_SET_POWER,
    6.71 +  OID_PNP_QUERY_POWER,
    6.72 +};
    6.73 +
    6.74 +/* return 4 or 8 depending on size of buffer */
    6.75 +#define HANDLE_STAT_RETURN \
    6.76 +  {if (InformationBufferLength == 4) { \
    6.77 +    len = 4; *BytesNeeded = 8; \
    6.78 +    } else { \
    6.79 +    len = 8; \
    6.80 +    } }
    6.81 +
    6.82 +NDIS_STATUS
    6.83 +XenNet_QueryInformation(
    6.84 +  IN NDIS_HANDLE MiniportAdapterContext,
    6.85 +  IN NDIS_OID Oid,
    6.86 +  IN PVOID InformationBuffer,
    6.87 +  IN ULONG InformationBufferLength,
    6.88 +  OUT PULONG BytesWritten,
    6.89 +  OUT PULONG BytesNeeded)
    6.90 +{
    6.91 +  struct xennet_info *xi = MiniportAdapterContext;
    6.92 +  UCHAR vendor_desc[] = XN_VENDOR_DESC;
    6.93 +  ULONG64 temp_data;
    6.94 +  PVOID data = &temp_data;
    6.95 +  UINT len = 4;
    6.96 +  BOOLEAN used_temp_buffer = TRUE;
    6.97 +  NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    6.98 +  PNDIS_TASK_OFFLOAD_HEADER ntoh;
    6.99 +  PNDIS_TASK_OFFLOAD nto;
   6.100 +  PNDIS_TASK_TCP_IP_CHECKSUM nttic;
   6.101 +  PNDIS_TASK_TCP_LARGE_SEND nttls;
   6.102 +  PNDIS_PNP_CAPABILITIES npc;
   6.103 +
   6.104 +  *BytesNeeded = 0;
   6.105 +  *BytesWritten = 0;
   6.106 +
   6.107 +// FUNCTION_ENTER()
   6.108 +
   6.109 +  switch(Oid)
   6.110 +  {
   6.111 +    case OID_GEN_SUPPORTED_LIST:
   6.112 +      data = supported_oids;
   6.113 +      len = sizeof(supported_oids);
   6.114 +      break;
   6.115 +    case OID_GEN_HARDWARE_STATUS:
   6.116 +      if (!xi->connected)
   6.117 +      {
   6.118 +        temp_data = NdisHardwareStatusInitializing;
   6.119 +        FUNCTION_MSG("NdisHardwareStatusInitializing\n");
   6.120 +      }
   6.121 +      else
   6.122 +      {
   6.123 +        temp_data = NdisHardwareStatusReady;
   6.124 +        FUNCTION_MSG("NdisHardwareStatusReady\n");
   6.125 +      }
   6.126 +      break;
   6.127 +    case OID_GEN_MEDIA_SUPPORTED:
   6.128 +      temp_data = NdisMedium802_3;
   6.129 +      break;
   6.130 +    case OID_GEN_MEDIA_IN_USE:
   6.131 +      temp_data = NdisMedium802_3;
   6.132 +      break;
   6.133 +    case OID_GEN_MAXIMUM_LOOKAHEAD:
   6.134 +      temp_data = MAX_LOOKAHEAD_LENGTH; //xi->config_mtu;
   6.135 +      break;
   6.136 +    case OID_GEN_MAXIMUM_FRAME_SIZE:
   6.137 +      temp_data = xi->config_mtu;
   6.138 +      break;
   6.139 +    case OID_GEN_LINK_SPEED:
   6.140 +      temp_data = 10000000; /* 1Gb */
   6.141 +      break;
   6.142 +    case OID_GEN_TRANSMIT_BUFFER_SPACE:
   6.143 +      /* multiply this by some small number as we can queue additional packets */
   6.144 +      temp_data = PAGE_SIZE * NET_TX_RING_SIZE * 4;
   6.145 +      break;
   6.146 +    case OID_GEN_RECEIVE_BUFFER_SPACE:
   6.147 +      temp_data = PAGE_SIZE * NET_RX_RING_SIZE * 2;
   6.148 +      break;
   6.149 +    case OID_GEN_TRANSMIT_BLOCK_SIZE:
   6.150 +      temp_data = PAGE_SIZE; //XN_MAX_PKT_SIZE;
   6.151 +      break;
   6.152 +    case OID_GEN_RECEIVE_BLOCK_SIZE:
   6.153 +      temp_data = PAGE_SIZE; //XN_MAX_PKT_SIZE;
   6.154 +      break;
   6.155 +    case OID_GEN_VENDOR_ID:
   6.156 +      temp_data = 0xFFFFFF; // Not guaranteed to be XENSOURCE_MAC_HDR;
   6.157 +      break;
   6.158 +    case OID_GEN_VENDOR_DESCRIPTION:
   6.159 +      data = vendor_desc;
   6.160 +      len = sizeof(vendor_desc);
   6.161 +      break;
   6.162 +    case OID_GEN_CURRENT_PACKET_FILTER:
   6.163 +      temp_data = xi->packet_filter;
   6.164 +      break;
   6.165 +    case OID_GEN_CURRENT_LOOKAHEAD:
   6.166 +      temp_data = xi->current_lookahead;
   6.167 +      break;
   6.168 +    case OID_GEN_DRIVER_VERSION:
   6.169 +      temp_data = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
   6.170 +      len = 2;
   6.171 +      break;
   6.172 +    case OID_GEN_VENDOR_DRIVER_VERSION:
   6.173 +      temp_data = VENDOR_DRIVER_VERSION;
   6.174 +      len = 4;
   6.175 +      break;
   6.176 +    case OID_GEN_MAXIMUM_TOTAL_SIZE:
   6.177 +      temp_data = xi->config_mtu + XN_HDR_SIZE;
   6.178 +      break;
   6.179 +    case OID_GEN_MAC_OPTIONS:
   6.180 +      temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 
   6.181 +        NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
   6.182 +        NDIS_MAC_OPTION_NO_LOOPBACK;
   6.183 +      break;
   6.184 +    case OID_GEN_MEDIA_CONNECT_STATUS:
   6.185 +      if (xi->connected && !xi->inactive)
   6.186 +        temp_data = NdisMediaStateConnected;
   6.187 +      else
   6.188 +        temp_data = NdisMediaStateDisconnected;
   6.189 +      break;
   6.190 +    case OID_GEN_MAXIMUM_SEND_PACKETS:
   6.191 +      /* this is actually ignored for deserialised drivers like us */
   6.192 +      temp_data = 0; //XN_MAX_SEND_PKTS;
   6.193 +      break;
   6.194 +    case OID_GEN_XMIT_OK:
   6.195 +      temp_data = xi->stat_tx_ok;
   6.196 +      HANDLE_STAT_RETURN;
   6.197 +      break;
   6.198 +    case OID_GEN_RCV_OK:
   6.199 +      temp_data = xi->stat_rx_ok;
   6.200 +      HANDLE_STAT_RETURN;
   6.201 +      break;
   6.202 +    case OID_GEN_XMIT_ERROR:
   6.203 +      temp_data = xi->stat_tx_error;
   6.204 +      HANDLE_STAT_RETURN;
   6.205 +      break;
   6.206 +    case OID_GEN_RCV_ERROR:
   6.207 +      temp_data = xi->stat_rx_error;
   6.208 +      HANDLE_STAT_RETURN;
   6.209 +      break;
   6.210 +    case OID_GEN_RCV_NO_BUFFER:
   6.211 +      temp_data = xi->stat_rx_no_buffer;
   6.212 +      HANDLE_STAT_RETURN;
   6.213 +      break;
   6.214 +    case OID_802_3_PERMANENT_ADDRESS:
   6.215 +      data = xi->perm_mac_addr;
   6.216 +      len = ETH_ALEN;
   6.217 +      break;
   6.218 +    case OID_802_3_CURRENT_ADDRESS:
   6.219 +      data = xi->curr_mac_addr;
   6.220 +      len = ETH_ALEN;
   6.221 +      break;
   6.222 +    case OID_802_3_RCV_ERROR_ALIGNMENT:
   6.223 +    case OID_802_3_XMIT_ONE_COLLISION:
   6.224 +    case OID_802_3_XMIT_MORE_COLLISIONS:
   6.225 +      temp_data = 0;
   6.226 +      HANDLE_STAT_RETURN;
   6.227 +      break;
   6.228 +    case OID_802_3_MULTICAST_LIST:
   6.229 +      data = xi->multicast_list;
   6.230 +      len = xi->multicast_list_size * 6;
   6.231 +      break;
   6.232 +    case OID_802_3_MAXIMUM_LIST_SIZE:
   6.233 +      temp_data = MULTICAST_LIST_MAX_SIZE;
   6.234 +      break;
   6.235 +    case OID_TCP_TASK_OFFLOAD:
   6.236 +      KdPrint(("Get OID_TCP_TASK_OFFLOAD\n"));
   6.237 +      /* it's times like this that C really sucks */
   6.238 +
   6.239 +      len = sizeof(NDIS_TASK_OFFLOAD_HEADER);
   6.240 +
   6.241 +      if (xi->config_csum)
   6.242 +      {
   6.243 +        len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   6.244 +          + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   6.245 +      }
   6.246 +
   6.247 +      if (xi->config_gso)
   6.248 +      {
   6.249 +        len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   6.250 +          + sizeof(NDIS_TASK_TCP_LARGE_SEND);
   6.251 +      }
   6.252 +
   6.253 +      //len += 1024;
   6.254 +
   6.255 +      if (len > InformationBufferLength)
   6.256 +      {
   6.257 +          break;
   6.258 +      }
   6.259 +
   6.260 +      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
   6.261 +      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
   6.262 +        || ntoh->Size != sizeof(*ntoh)
   6.263 +        || !(
   6.264 +          ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation
   6.265 +          || (ntoh->EncapsulationFormat.Encapsulation == UNSPECIFIED_Encapsulation
   6.266 +              && ntoh->EncapsulationFormat.EncapsulationHeaderSize == XN_HDR_SIZE)))
   6.267 +      {
   6.268 +        status = NDIS_STATUS_NOT_SUPPORTED;
   6.269 +        break;
   6.270 +      }
   6.271 +      ntoh->OffsetFirstTask = 0; 
   6.272 +      nto = NULL;
   6.273 +
   6.274 +      if (xi->config_csum)
   6.275 +      {
   6.276 +        if (ntoh->OffsetFirstTask == 0)
   6.277 +        {
   6.278 +          ntoh->OffsetFirstTask = ntoh->Size;
   6.279 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
   6.280 +        }
   6.281 +        else
   6.282 +        {
   6.283 +          nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   6.284 +            + nto->TaskBufferLength;
   6.285 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
   6.286 +        }
   6.287 +        /* fill in first nto */
   6.288 +        nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   6.289 +        nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   6.290 +        nto->Task = TcpIpChecksumNdisTask;
   6.291 +        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   6.292 +
   6.293 +        KdPrint(("config_csum enabled\n"));
   6.294 +        KdPrint(("nto = %p\n", nto));
   6.295 +        KdPrint(("nto->Size = %d\n", nto->Size));
   6.296 +        KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
   6.297 +
   6.298 +        /* fill in checksum offload struct */
   6.299 +        nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   6.300 +        nttic->V4Transmit.IpChecksum = 0;
   6.301 +        nttic->V4Transmit.IpOptionsSupported = 0;
   6.302 +        nttic->V4Transmit.TcpChecksum = 1;
   6.303 +        nttic->V4Transmit.TcpOptionsSupported = 1;
   6.304 +        nttic->V4Transmit.UdpChecksum = 1;
   6.305 +        nttic->V4Receive.IpChecksum = 1;
   6.306 +        nttic->V4Receive.IpOptionsSupported = 1;
   6.307 +        nttic->V4Receive.TcpChecksum = 1;
   6.308 +        nttic->V4Receive.TcpOptionsSupported = 1;
   6.309 +        nttic->V4Receive.UdpChecksum = 1;
   6.310 +        nttic->V6Transmit.IpOptionsSupported = 0;
   6.311 +        nttic->V6Transmit.TcpOptionsSupported = 0;
   6.312 +        nttic->V6Transmit.TcpChecksum = 0;
   6.313 +        nttic->V6Transmit.UdpChecksum = 0;
   6.314 +        nttic->V6Receive.IpOptionsSupported = 0;
   6.315 +        nttic->V6Receive.TcpOptionsSupported = 0;
   6.316 +        nttic->V6Receive.TcpChecksum = 0;
   6.317 +        nttic->V6Receive.UdpChecksum = 0;
   6.318 +      }
   6.319 +      if (xi->config_gso)
   6.320 +      {
   6.321 +        if (ntoh->OffsetFirstTask == 0)
   6.322 +        {
   6.323 +          ntoh->OffsetFirstTask = ntoh->Size;
   6.324 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
   6.325 +        }
   6.326 +        else
   6.327 +        {
   6.328 +          nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   6.329 +            + nto->TaskBufferLength;
   6.330 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
   6.331 +        }
   6.332 +  
   6.333 +        /* fill in second nto */
   6.334 +        nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   6.335 +        nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   6.336 +        nto->Task = TcpLargeSendNdisTask;
   6.337 +        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
   6.338 +
   6.339 +        KdPrint(("config_gso enabled\n"));
   6.340 +        KdPrint(("nto = %p\n", nto));
   6.341 +        KdPrint(("nto->Size = %d\n", nto->Size));
   6.342 +        KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
   6.343 +  
   6.344 +        /* fill in large send struct */
   6.345 +        nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
   6.346 +        nttls->Version = 0;
   6.347 +        nttls->MaxOffLoadSize = xi->config_gso;
   6.348 +        nttls->MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
   6.349 +        nttls->TcpOptions = FALSE; /* linux can't handle this */
   6.350 +        nttls->IpOptions = FALSE; /* linux can't handle this */
   6.351 +        KdPrint(("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions)));        
   6.352 +      }
   6.353 +
   6.354 +      if (nto)
   6.355 +        nto->OffsetNextTask = 0; /* last one */
   6.356 +
   6.357 +      used_temp_buffer = FALSE;
   6.358 +      break;
   6.359 +    case OID_IP4_OFFLOAD_STATS:
   6.360 +    case OID_IP6_OFFLOAD_STATS:
   6.361 +      /* these are called often so just ignore then quietly */
   6.362 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.363 +      break;
   6.364 +
   6.365 +    case OID_PNP_CAPABILITIES:
   6.366 +      KdPrint(("Get OID_PNP_CAPABILITIES\n"));
   6.367 +      len = sizeof(NDIS_PNP_CAPABILITIES);
   6.368 +      if (len > InformationBufferLength)
   6.369 +        break;
   6.370 +      npc = (PNDIS_PNP_CAPABILITIES)InformationBuffer;
   6.371 +      npc->Flags = 0;
   6.372 +      npc->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
   6.373 +      npc->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
   6.374 +      npc->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
   6.375 +      used_temp_buffer = FALSE;
   6.376 +      break;
   6.377 +    case OID_PNP_QUERY_POWER:
   6.378 +      KdPrint(("Get OID_PNP_CAPABILITIES\n"));
   6.379 +      used_temp_buffer = FALSE;
   6.380 +      break;
   6.381 +
   6.382 +    default:
   6.383 +      KdPrint(("Get Unknown OID 0x%x\n", Oid));
   6.384 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.385 +  }
   6.386 +
   6.387 +  if (!NT_SUCCESS(status))
   6.388 +  {
   6.389 +    //FUNCTION_EXIT_STATUS(status);
   6.390 +    return status;
   6.391 +  }
   6.392 +
   6.393 +  if (len > InformationBufferLength)
   6.394 +  {
   6.395 +    *BytesNeeded = len;
   6.396 +    FUNCTION_MSG("(BUFFER_TOO_SHORT %d > %d)\n", len, InformationBufferLength);
   6.397 +    return NDIS_STATUS_BUFFER_TOO_SHORT;
   6.398 +  }
   6.399 +
   6.400 +  *BytesWritten = len;
   6.401 +  if (len && used_temp_buffer)
   6.402 +  {
   6.403 +    NdisMoveMemory((PUCHAR)InformationBuffer, data, len);
   6.404 +  }
   6.405 +
   6.406 +  //KdPrint(("Got OID 0x%x\n", Oid));
   6.407 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.408 +
   6.409 +  return status;
   6.410 +}
   6.411 +
   6.412 +NDIS_STATUS
   6.413 +XenNet_SetInformation(
   6.414 +  IN NDIS_HANDLE MiniportAdapterContext,
   6.415 +  IN NDIS_OID Oid,
   6.416 +  IN PVOID InformationBuffer,
   6.417 +  IN ULONG InformationBufferLength,
   6.418 +  OUT PULONG BytesRead,
   6.419 +  OUT PULONG BytesNeeded
   6.420 +  )
   6.421 +{
   6.422 +  NTSTATUS status;
   6.423 +  ULONG i;
   6.424 +  struct xennet_info *xi = MiniportAdapterContext;
   6.425 +  PULONG64 data = InformationBuffer;
   6.426 +  PNDIS_TASK_OFFLOAD_HEADER ntoh;
   6.427 +  PNDIS_TASK_OFFLOAD nto;
   6.428 +  PNDIS_TASK_TCP_IP_CHECKSUM nttic = NULL;
   6.429 +  PNDIS_TASK_TCP_LARGE_SEND nttls = NULL;
   6.430 +  UCHAR *multicast_list;
   6.431 +  int offset;
   6.432 +
   6.433 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   6.434 +
   6.435 +  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   6.436 +  UNREFERENCED_PARAMETER(InformationBufferLength);
   6.437 +  UNREFERENCED_PARAMETER(BytesRead);
   6.438 +  UNREFERENCED_PARAMETER(BytesNeeded);
   6.439 +
   6.440 +  switch(Oid)
   6.441 +  {
   6.442 +    case OID_GEN_SUPPORTED_LIST:
   6.443 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.444 +      KdPrint(("Unsupported set OID_GEN_SUPPORTED_LIST\n"));
   6.445 +      break;
   6.446 +    case OID_GEN_HARDWARE_STATUS:
   6.447 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.448 +      KdPrint(("Unsupported set OID_GEN_HARDWARE_STATUS\n"));
   6.449 +      break;
   6.450 +    case OID_GEN_MEDIA_SUPPORTED:
   6.451 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.452 +      KdPrint(("Unsupported set OID_GEN_MEDIA_SUPPORTED\n"));
   6.453 +      break;
   6.454 +    case OID_GEN_MEDIA_IN_USE:
   6.455 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.456 +      KdPrint(("Unsupported set OID_GEN_MEDIA_IN_USE\n"));
   6.457 +      break;
   6.458 +    case OID_GEN_MAXIMUM_LOOKAHEAD:
   6.459 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.460 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_LOOKAHEAD\n"));
   6.461 +      break;
   6.462 +    case OID_GEN_MAXIMUM_FRAME_SIZE:
   6.463 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.464 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_FRAME_SIZE\n"));
   6.465 +      break;
   6.466 +    case OID_GEN_LINK_SPEED:
   6.467 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.468 +      KdPrint(("Unsupported set OID_GEN_LINK_SPEED\n"));
   6.469 +      break;
   6.470 +    case OID_GEN_TRANSMIT_BUFFER_SPACE:
   6.471 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.472 +      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
   6.473 +      break;
   6.474 +    case OID_GEN_RECEIVE_BUFFER_SPACE:
   6.475 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.476 +      KdPrint(("Unsupported set OID_GEN_RECEIVE_BUFFER_SPACE\n"));
   6.477 +      break;
   6.478 +    case OID_GEN_TRANSMIT_BLOCK_SIZE:
   6.479 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.480 +      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
   6.481 +      break;
   6.482 +    case OID_GEN_RECEIVE_BLOCK_SIZE:
   6.483 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.484 +      KdPrint(("Unsupported set OID_GEN_RECEIVE_BLOCK_SIZE\n"));
   6.485 +      break;
   6.486 +    case OID_GEN_VENDOR_ID:
   6.487 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.488 +      KdPrint(("Unsupported set OID_GEN_VENDOR_ID\n"));
   6.489 +      break;
   6.490 +    case OID_GEN_VENDOR_DESCRIPTION:
   6.491 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.492 +      KdPrint(("Unsupported set OID_GEN_VENDOR_DESCRIPTION\n"));
   6.493 +      break;
   6.494 +    case OID_GEN_CURRENT_PACKET_FILTER:
   6.495 +      KdPrint(("Set OID_GEN_CURRENT_PACKET_FILTER (xi = %p)\n", xi));
   6.496 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_DIRECTED)
   6.497 +        KdPrint(("  NDIS_PACKET_TYPE_DIRECTED\n"));
   6.498 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_MULTICAST)
   6.499 +        KdPrint(("  NDIS_PACKET_TYPE_MULTICAST\n"));
   6.500 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_MULTICAST)
   6.501 +        KdPrint(("  NDIS_PACKET_TYPE_ALL_MULTICAST\n"));
   6.502 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_BROADCAST)
   6.503 +        KdPrint(("  NDIS_PACKET_TYPE_BROADCAST\n"));
   6.504 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_PROMISCUOUS)
   6.505 +        KdPrint(("  NDIS_PACKET_TYPE_PROMISCUOUS\n"));
   6.506 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
   6.507 +        KdPrint(("  NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n"));
   6.508 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_LOCAL)
   6.509 +        KdPrint(("  NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n"));  
   6.510 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_FUNCTIONAL)
   6.511 +        KdPrint(("  NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n"));
   6.512 +      if (*(ULONG *)data & NDIS_PACKET_TYPE_GROUP)
   6.513 +        KdPrint(("  NDIS_PACKET_TYPE_GROUP (not supported)\n"));
   6.514 +      if (*(ULONG *)data & ~SUPPORTED_PACKET_FILTERS)
   6.515 +      {
   6.516 +        status = NDIS_STATUS_NOT_SUPPORTED;
   6.517 +        KdPrint(("  returning NDIS_STATUS_NOT_SUPPORTED\n"));
   6.518 +        break;
   6.519 +      }
   6.520 +      xi->packet_filter = *(ULONG *)data;
   6.521 +      status = NDIS_STATUS_SUCCESS;
   6.522 +      break;
   6.523 +    case OID_GEN_CURRENT_LOOKAHEAD:
   6.524 +      xi->current_lookahead = *(ULONG *)data;
   6.525 +      KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi));
   6.526 +      status = NDIS_STATUS_SUCCESS;
   6.527 +      break;
   6.528 +    case OID_GEN_DRIVER_VERSION:
   6.529 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.530 +      KdPrint(("Unsupported set OID_GEN_DRIVER_VERSION\n"));
   6.531 +      break;
   6.532 +    case OID_GEN_MAXIMUM_TOTAL_SIZE:
   6.533 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.534 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
   6.535 +      break;
   6.536 +    case OID_GEN_PROTOCOL_OPTIONS:
   6.537 +      KdPrint(("Unsupported set OID_GEN_PROTOCOL_OPTIONS\n"));
   6.538 +      // TODO - actually do this...
   6.539 +      status = NDIS_STATUS_SUCCESS;
   6.540 +      break;
   6.541 +    case OID_GEN_MAC_OPTIONS:
   6.542 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.543 +      KdPrint(("Unsupported set OID_GEN_MAC_OPTIONS\n"));
   6.544 +      break;
   6.545 +    case OID_GEN_MEDIA_CONNECT_STATUS:
   6.546 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.547 +      KdPrint(("Unsupported set OID_GEN_MEDIA_CONNECT_STATUS\n"));
   6.548 +      break;
   6.549 +    case OID_GEN_MAXIMUM_SEND_PACKETS:
   6.550 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.551 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_SEND_PACKETS\n"));
   6.552 +      break;
   6.553 +    case OID_GEN_XMIT_OK:
   6.554 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.555 +      KdPrint(("Unsupported set OID_GEN_XMIT_OK\n"));
   6.556 +      break;
   6.557 +    case OID_GEN_RCV_OK:
   6.558 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.559 +      KdPrint(("Unsupported set OID_GEN_RCV_OK\n"));
   6.560 +      break;
   6.561 +    case OID_GEN_XMIT_ERROR:
   6.562 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.563 +      KdPrint(("Unsupported set OID_GEN_XMIT_ERROR\n"));
   6.564 +      break;
   6.565 +    case OID_GEN_RCV_ERROR:
   6.566 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.567 +      KdPrint(("Unsupported set OID_GEN_RCV_ERROR\n"));
   6.568 +      break;
   6.569 +    case OID_GEN_RCV_NO_BUFFER:
   6.570 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.571 +      KdPrint(("Unsupported set OID_GEN_RCV_NO_BUFFER\n"));
   6.572 +      break;
   6.573 +    case OID_802_3_PERMANENT_ADDRESS:
   6.574 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.575 +      KdPrint(("Unsupported set OID_802_3_PERMANENT_ADDRESS\n"));
   6.576 +      break;
   6.577 +    case OID_802_3_CURRENT_ADDRESS:
   6.578 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.579 +      KdPrint(("Unsupported set OID_802_3_CURRENT_ADDRESS\n"));
   6.580 +      break;
   6.581 +    case OID_802_3_MULTICAST_LIST:
   6.582 +      KdPrint(("     Set OID_802_3_MULTICAST_LIST\n"));
   6.583 +      KdPrint(("       Length = %d\n", InformationBufferLength));
   6.584 +      KdPrint(("       Entries = %d\n", InformationBufferLength / 6));
   6.585 +      if (InformationBufferLength > MULTICAST_LIST_MAX_SIZE * 6)
   6.586 +      {
   6.587 +        status = NDIS_STATUS_MULTICAST_FULL;
   6.588 +        break;
   6.589 +      }
   6.590 +      
   6.591 +      if (InformationBufferLength % 6 != 0)
   6.592 +      {
   6.593 +        status = NDIS_STATUS_MULTICAST_FULL;
   6.594 +        break;
   6.595 +      }
   6.596 +      multicast_list = InformationBuffer;
   6.597 +      for (i = 0; i < InformationBufferLength / 6; i++)
   6.598 +      {
   6.599 +        if (!(multicast_list[i * 6 + 0] & 0x01))
   6.600 +        {
   6.601 +          KdPrint(("       Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i,
   6.602 +            (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1], 
   6.603 +            (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3], 
   6.604 +            (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]));
   6.605 +          /* the docs say that we should return NDIS_STATUS_MULTICAST_FULL if we get an invalid multicast address but I'm not sure if that's the case... */
   6.606 +        }
   6.607 +      }
   6.608 +      memcpy(xi->multicast_list, InformationBuffer, InformationBufferLength);
   6.609 +      xi->multicast_list_size = InformationBufferLength / 6;
   6.610 +      status = NDIS_STATUS_SUCCESS;
   6.611 +      break;
   6.612 +    case OID_802_3_MAXIMUM_LIST_SIZE:
   6.613 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.614 +      KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
   6.615 +      break;
   6.616 +    case OID_TCP_TASK_OFFLOAD:
   6.617 +      status = NDIS_STATUS_SUCCESS;
   6.618 +      KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
   6.619 +      // we should disable everything here, then enable what has been set
   6.620 +      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
   6.621 +      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION)
   6.622 +      {
   6.623 +        KdPrint(("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION));
   6.624 +        status = NDIS_STATUS_INVALID_DATA;
   6.625 +        break;
   6.626 +      }
   6.627 +      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER))
   6.628 +      {
   6.629 +        KdPrint(("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER)));
   6.630 +        status = NDIS_STATUS_INVALID_DATA;
   6.631 +        break;
   6.632 +      }
   6.633 +      *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
   6.634 +      offset = ntoh->OffsetFirstTask;
   6.635 +      nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
   6.636 +      while (offset != 0)
   6.637 +      {
   6.638 +        *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
   6.639 +        nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
   6.640 +        switch (nto->Task)
   6.641 +        {
   6.642 +        case TcpIpChecksumNdisTask:
   6.643 +          *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   6.644 +          nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   6.645 +          KdPrint(("TcpIpChecksumNdisTask\n"));
   6.646 +          KdPrint(("  V4Transmit.IpOptionsSupported  = %d\n", nttic->V4Transmit.IpOptionsSupported));
   6.647 +          KdPrint(("  V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported));
   6.648 +          KdPrint(("  V4Transmit.TcpChecksum         = %d\n", nttic->V4Transmit.TcpChecksum));
   6.649 +          KdPrint(("  V4Transmit.UdpChecksum         = %d\n", nttic->V4Transmit.UdpChecksum));
   6.650 +          KdPrint(("  V4Transmit.IpChecksum          = %d\n", nttic->V4Transmit.IpChecksum));
   6.651 +          KdPrint(("  V4Receive.IpOptionsSupported   = %d\n", nttic->V4Receive.IpOptionsSupported));
   6.652 +          KdPrint(("  V4Receive.TcpOptionsSupported  = %d\n", nttic->V4Receive.TcpOptionsSupported));
   6.653 +          KdPrint(("  V4Receive.TcpChecksum          = %d\n", nttic->V4Receive.TcpChecksum));
   6.654 +          KdPrint(("  V4Receive.UdpChecksum          = %d\n", nttic->V4Receive.UdpChecksum));
   6.655 +          KdPrint(("  V4Receive.IpChecksum           = %d\n", nttic->V4Receive.IpChecksum));
   6.656 +          KdPrint(("  V6Transmit.IpOptionsSupported  = %d\n", nttic->V6Transmit.IpOptionsSupported));
   6.657 +          KdPrint(("  V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported));
   6.658 +          KdPrint(("  V6Transmit.TcpChecksum         = %d\n", nttic->V6Transmit.TcpChecksum));
   6.659 +          KdPrint(("  V6Transmit.UdpChecksum         = %d\n", nttic->V6Transmit.UdpChecksum));
   6.660 +          KdPrint(("  V6Receive.IpOptionsSupported   = %d\n", nttic->V6Receive.IpOptionsSupported));
   6.661 +          KdPrint(("  V6Receive.TcpOptionsSupported  = %d\n", nttic->V6Receive.TcpOptionsSupported));
   6.662 +          KdPrint(("  V6Receive.TcpChecksum          = %d\n", nttic->V6Receive.TcpChecksum));
   6.663 +          KdPrint(("  V6Receive.UdpChecksum          = %d\n", nttic->V6Receive.UdpChecksum));
   6.664 +          /* check for stuff we outright don't support */
   6.665 +          if (nttic->V6Transmit.IpOptionsSupported ||
   6.666 +            nttic->V6Transmit.TcpOptionsSupported ||
   6.667 +            nttic->V6Transmit.TcpChecksum ||
   6.668 +            nttic->V6Transmit.UdpChecksum ||
   6.669 +            nttic->V6Receive.IpOptionsSupported ||
   6.670 +            nttic->V6Receive.TcpOptionsSupported ||
   6.671 +            nttic->V6Receive.TcpChecksum ||
   6.672 +            nttic->V6Receive.UdpChecksum)
   6.673 +          {
   6.674 +            KdPrint(("IPv6 offload not supported\n"));
   6.675 +            status = NDIS_STATUS_INVALID_DATA;
   6.676 +            nttic = NULL;
   6.677 +            break;
   6.678 +          }
   6.679 +          if (nttic->V4Transmit.IpOptionsSupported ||
   6.680 +            nttic->V4Transmit.IpChecksum)
   6.681 +          {
   6.682 +            KdPrint(("IPv4 IP Transmit offload not supported\n"));
   6.683 +            status = NDIS_STATUS_INVALID_DATA;
   6.684 +            nttic = NULL;
   6.685 +            break;
   6.686 +          }
   6.687 +          if (nttic->V4Receive.IpOptionsSupported &&
   6.688 +            !nttic->V4Receive.IpChecksum)
   6.689 +          {
   6.690 +            KdPrint(("Invalid combination\n"));
   6.691 +            status = NDIS_STATUS_INVALID_DATA;
   6.692 +            nttic = NULL;
   6.693 +            break;
   6.694 +          }
   6.695 +          if (nttic->V4Transmit.TcpOptionsSupported &&
   6.696 +            !nttic->V4Transmit.TcpChecksum)
   6.697 +          {
   6.698 +            KdPrint(("Invalid combination\n"));
   6.699 +            status = NDIS_STATUS_INVALID_DATA;
   6.700 +            nttic = NULL;
   6.701 +            break;
   6.702 +          }
   6.703 +          if (nttic->V4Receive.TcpOptionsSupported &&
   6.704 +            !nttic->V4Receive.TcpChecksum)
   6.705 +          {
   6.706 +            KdPrint(("Invalid combination\n"));
   6.707 +            status = NDIS_STATUS_INVALID_DATA;
   6.708 +            nttic = NULL;
   6.709 +            break;
   6.710 +          }
   6.711 +          break;
   6.712 +        case TcpLargeSendNdisTask:
   6.713 +          *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND);
   6.714 +          KdPrint(("TcpLargeSendNdisTask\n"));
   6.715 +          nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
   6.716 +          KdPrint(("  MaxOffLoadSize                 = %d\n", nttls->MaxOffLoadSize));
   6.717 +          KdPrint(("  MinSegmentCount                = %d\n", nttls->MinSegmentCount));
   6.718 +          KdPrint(("  TcpOptions                     = %d\n", nttls->TcpOptions));
   6.719 +          KdPrint(("  IpOptions                      = %d\n", nttls->IpOptions));
   6.720 +          if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS)
   6.721 +          {
   6.722 +            KdPrint(("     MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS));
   6.723 +            status = NDIS_STATUS_INVALID_DATA;
   6.724 +            nttls = NULL;
   6.725 +            break;
   6.726 +          }
   6.727 +          if (nttls->IpOptions)
   6.728 +          {
   6.729 +            KdPrint(("     IpOptions not supported\n"));
   6.730 +            status = NDIS_STATUS_INVALID_DATA;
   6.731 +            nttls = NULL;
   6.732 +            break;
   6.733 +          }
   6.734 +          if (nttls->TcpOptions)
   6.735 +          {
   6.736 +            KdPrint(("     TcpOptions not supported\n"));
   6.737 +            status = NDIS_STATUS_INVALID_DATA;
   6.738 +            nttls = NULL;
   6.739 +            break;
   6.740 +          }
   6.741 +          break;
   6.742 +        default:
   6.743 +          KdPrint(("     Unknown Task %d\n", nto->Task));
   6.744 +        }
   6.745 +        offset = nto->OffsetNextTask;
   6.746 +      }
   6.747 +      if (nttic != NULL)
   6.748 +        xi->setting_csum = *nttic;
   6.749 +      else
   6.750 +      {
   6.751 +        RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
   6.752 +        KdPrint(("     csum offload disabled\n", nto->Task));
   6.753 +      }        
   6.754 +      if (nttls != NULL)
   6.755 +        xi->setting_max_offload = nttls->MaxOffLoadSize;
   6.756 +      else
   6.757 +      {
   6.758 +        xi->setting_max_offload = 0;
   6.759 +        KdPrint(("     LSO disabled\n", nto->Task));
   6.760 +      }
   6.761 +      break;
   6.762 +    case OID_PNP_SET_POWER:
   6.763 +      KdPrint(("     Set OID_PNP_SET_POWER\n"));
   6.764 +      xi->new_power_state = *(PNDIS_DEVICE_POWER_STATE)InformationBuffer;
   6.765 +      IoQueueWorkItem(xi->power_workitem, XenNet_SetPower, DelayedWorkQueue, xi);
   6.766 +      status = NDIS_STATUS_PENDING;
   6.767 +      break;
   6.768 +    default:
   6.769 +      KdPrint(("Set Unknown OID 0x%x\n", Oid));
   6.770 +      status = NDIS_STATUS_NOT_SUPPORTED;
   6.771 +      break;
   6.772 +  }
   6.773 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.774 +  return status;
   6.775 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xennet/xennet5_rx.c	Sat Apr 30 10:57:23 2011 +1000
     7.3 @@ -0,0 +1,1160 @@
     7.4 +/*
     7.5 +PV Net Driver for Windows Xen HVM Domains
     7.6 +Copyright (C) 2007 James Harper
     7.7 +Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     7.8 +
     7.9 +This program is free software; you can redistribute it and/or
    7.10 +modify it under the terms of the GNU General Public License
    7.11 +as published by the Free Software Foundation; either version 2
    7.12 +of the License, or (at your option) any later version.
    7.13 +
    7.14 +This program is distributed in the hope that it will be useful,
    7.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.17 +GNU General Public License for more details.
    7.18 +
    7.19 +You should have received a copy of the GNU General Public License
    7.20 +along with this program; if not, write to the Free Software
    7.21 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    7.22 +*/
    7.23 +
    7.24 +#include "xennet5.h"
    7.25 +
    7.26 +static LONG rx_pb_outstanding = 0;
    7.27 +
    7.28 +static __inline shared_buffer_t *
    7.29 +get_pb_from_freelist(struct xennet_info *xi)
    7.30 +{
    7.31 +  NDIS_STATUS status;
    7.32 +  shared_buffer_t *pb;
    7.33 +  PVOID ptr_ref;
    7.34 +
    7.35 +  if (stack_pop(xi->rx_pb_stack, &ptr_ref))
    7.36 +  {
    7.37 +    pb = ptr_ref;
    7.38 +    pb->ref_count = 1;
    7.39 +    InterlockedDecrement(&xi->rx_pb_free);
    7.40 +    InterlockedIncrement(&rx_pb_outstanding);
    7.41 +    return pb;
    7.42 +  }
    7.43 +
    7.44 +  /* don't allocate a new one if we are shutting down */
    7.45 +  if (xi->shutting_down)
    7.46 +    return NULL;
    7.47 +    
    7.48 +  status = NdisAllocateMemoryWithTag(&pb, sizeof(shared_buffer_t), XENNET_POOL_TAG);
    7.49 +  if (status != STATUS_SUCCESS)
    7.50 +  {
    7.51 +    return NULL;
    7.52 +  }
    7.53 +  status = NdisAllocateMemoryWithTag(&pb->virtual, PAGE_SIZE, XENNET_POOL_TAG);
    7.54 +  if (status != STATUS_SUCCESS)
    7.55 +  {
    7.56 +    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
    7.57 +    return NULL;
    7.58 +  }
    7.59 +  pb->gref = (grant_ref_t)xi->vectors.GntTbl_GrantAccess(xi->vectors.context, 0,
    7.60 +            (ULONG)(MmGetPhysicalAddress(pb->virtual).QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, (ULONG)'XNRX');
    7.61 +  if (pb->gref == INVALID_GRANT_REF)
    7.62 +  {
    7.63 +    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
    7.64 +    NdisFreeMemory(pb->virtual, PAGE_SIZE, 0);
    7.65 +    return NULL;
    7.66 +  }
    7.67 +  pb->offset = (USHORT)(ULONG_PTR)pb->virtual & (PAGE_SIZE - 1);
    7.68 +  NdisAllocateBuffer(&status, &pb->buffer, xi->rx_buffer_pool, (PUCHAR)pb->virtual, PAGE_SIZE);
    7.69 +  if (status != STATUS_SUCCESS)
    7.70 +  {
    7.71 +    xi->vectors.GntTbl_EndAccess(xi->vectors.context,
    7.72 +        pb->gref, FALSE, (ULONG)'XNRX');
    7.73 +    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
    7.74 +    NdisFreeMemory(pb->virtual, PAGE_SIZE, 0);
    7.75 +    return NULL;
    7.76 +  }
    7.77 +  InterlockedIncrement(&rx_pb_outstanding);
    7.78 +  pb->ref_count = 1;
    7.79 +  return pb;
    7.80 +}
    7.81 +
    7.82 +static __inline VOID
    7.83 +ref_pb(struct xennet_info *xi, shared_buffer_t *pb)
    7.84 +{
    7.85 +  UNREFERENCED_PARAMETER(xi);
    7.86 +  InterlockedIncrement(&pb->ref_count);
    7.87 +}
    7.88 +
    7.89 +static __inline VOID
    7.90 +put_pb_on_freelist(struct xennet_info *xi, shared_buffer_t *pb)
    7.91 +{
    7.92 +  if (InterlockedDecrement(&pb->ref_count) == 0)
    7.93 +  {
    7.94 +    NdisAdjustBufferLength(pb->buffer, PAGE_SIZE);
    7.95 +    NDIS_BUFFER_LINKAGE(pb->buffer) = NULL;
    7.96 +    pb->next = NULL;
    7.97 +    stack_push(xi->rx_pb_stack, pb);
    7.98 +    InterlockedIncrement(&xi->rx_pb_free);
    7.99 +    InterlockedDecrement(&rx_pb_outstanding);
   7.100 +  }
   7.101 +}
   7.102 +
   7.103 +// Called at DISPATCH_LEVEL with rx lock held
   7.104 +static NDIS_STATUS
   7.105 +XenNet_FillRing(struct xennet_info *xi)
   7.106 +{
   7.107 +  unsigned short id;
   7.108 +  shared_buffer_t *page_buf;
   7.109 +  ULONG i, notify;
   7.110 +  ULONG batch_target;
   7.111 +  RING_IDX req_prod = xi->rx.req_prod_pvt;
   7.112 +  netif_rx_request_t *req;
   7.113 +
   7.114 +  //FUNCTION_ENTER();
   7.115 +
   7.116 +  batch_target = xi->rx_target - (req_prod - xi->rx.rsp_cons);
   7.117 +
   7.118 +  if (batch_target < (xi->rx_target >> 2))
   7.119 +  {
   7.120 +    //FUNCTION_EXIT();
   7.121 +    return NDIS_STATUS_SUCCESS; /* only refill if we are less than 3/4 full already */
   7.122 +  }
   7.123 +
   7.124 +  for (i = 0; i < batch_target; i++)
   7.125 +  {
   7.126 +    page_buf = get_pb_from_freelist(xi);
   7.127 +    if (!page_buf)
   7.128 +    {
   7.129 +      KdPrint((__DRIVER_NAME "     Added %d out of %d buffers to rx ring (no free pages)\n", i, batch_target));
   7.130 +      break;
   7.131 +    }
   7.132 +    xi->rx_id_free--;
   7.133 +
   7.134 +    /* Give to netback */
   7.135 +    id = (USHORT)((req_prod + i) & (NET_RX_RING_SIZE - 1));
   7.136 +    ASSERT(xi->rx_ring_pbs[id] == NULL);
   7.137 +    xi->rx_ring_pbs[id] = page_buf;
   7.138 +    req = RING_GET_REQUEST(&xi->rx, req_prod + i);
   7.139 +    req->id = id;
   7.140 +    req->gref = page_buf->gref;
   7.141 +    ASSERT(req->gref != INVALID_GRANT_REF);
   7.142 +  }
   7.143 +  KeMemoryBarrier();
   7.144 +  xi->rx.req_prod_pvt = req_prod + i;
   7.145 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->rx, notify);
   7.146 +  if (notify)
   7.147 +  {
   7.148 +    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->event_channel);
   7.149 +  }
   7.150 +
   7.151 +  //FUNCTION_EXIT();
   7.152 +
   7.153 +  return NDIS_STATUS_SUCCESS;
   7.154 +}
   7.155 +
   7.156 +LONG total_allocated_packets = 0;
   7.157 +LONG dpc_limit_hit = 0;
   7.158 +LONG resource_packets = 0;
   7.159 +LARGE_INTEGER last_print_time;
   7.160 +
   7.161 +/* lock free */
   7.162 +static PNDIS_PACKET
   7.163 +get_packet_from_freelist(struct xennet_info *xi)
   7.164 +{
   7.165 +  NDIS_STATUS status;
   7.166 +  PNDIS_PACKET packet;
   7.167 +  PVOID ptr_ref;
   7.168 +
   7.169 +  if (stack_pop(xi->rx_packet_stack, &ptr_ref))
   7.170 +  {
   7.171 +    packet = ptr_ref;
   7.172 +    InterlockedIncrement(&total_allocated_packets);
   7.173 +    return packet;
   7.174 +  }
   7.175 +  
   7.176 +  if (xi->rx_shutting_down) /* don't keep allocating new packets on shutdown */
   7.177 +    return NULL;
   7.178 +
   7.179 +  NdisAllocatePacket(&status, &packet, xi->rx_packet_pool);
   7.180 +  if (status != NDIS_STATUS_SUCCESS)
   7.181 +  {
   7.182 +    KdPrint((__DRIVER_NAME "     cannot allocate packet\n"));
   7.183 +    return NULL;
   7.184 +  }
   7.185 +  NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
   7.186 +  NdisZeroMemory(packet->MiniportReservedEx, sizeof(packet->MiniportReservedEx));
   7.187 +  InterlockedIncrement(&total_allocated_packets);
   7.188 +  return packet;
   7.189 +}
   7.190 +
   7.191 +/* lock free */
   7.192 +static VOID
   7.193 +put_packet_on_freelist(struct xennet_info *xi, PNDIS_PACKET packet)
   7.194 +{
   7.195 +  LARGE_INTEGER current_time;
   7.196 +  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   7.197 +
   7.198 +  UNREFERENCED_PARAMETER(xi);
   7.199 +  
   7.200 +  InterlockedDecrement(&total_allocated_packets);
   7.201 +
   7.202 +  NdisReinitializePacket(packet);
   7.203 +  RtlZeroMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(packet), sizeof(NDIS_PACKET_EXTENSION));
   7.204 +  csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   7.205 +    packet, TcpIpChecksumPacketInfo);
   7.206 +  csum_info->Value = 0;
   7.207 +
   7.208 +  stack_push(xi->rx_packet_stack, packet);
   7.209 +
   7.210 +  KeQuerySystemTime(&current_time);
   7.211 +  if ((current_time.QuadPart - last_print_time.QuadPart) / 10000 > 5000)
   7.212 +  {
   7.213 +    last_print_time.QuadPart = current_time.QuadPart;
   7.214 +    KdPrint(("total_allocated_packets = %d, rx_outstanding = %d, resource_packets = %d, dpc_limit_hit = %d, rx_pb_outstanding = %d, rx_pb_free = %d\n", total_allocated_packets, xi->rx_outstanding, resource_packets, dpc_limit_hit, rx_pb_outstanding, xi->rx_pb_free));
   7.215 +  }
   7.216 +}
   7.217 +
   7.218 +static PNDIS_PACKET
   7.219 +XenNet_MakePacket(struct xennet_info *xi, packet_info_t *pi)
   7.220 +{
   7.221 +  NDIS_STATUS status;
   7.222 +  PNDIS_PACKET packet;
   7.223 +  PNDIS_BUFFER out_buffer;
   7.224 +  USHORT new_ip4_length;
   7.225 +  PUCHAR header_va;
   7.226 +  ULONG out_remaining;
   7.227 +  ULONG tcp_length;
   7.228 +  ULONG header_extra;
   7.229 +  shared_buffer_t *header_buf;
   7.230 +
   7.231 +  //FUNCTION_ENTER();
   7.232 +  
   7.233 +  packet = get_packet_from_freelist(xi);
   7.234 +  if (packet == NULL)
   7.235 +  {
   7.236 +    /* buffers will be freed in MakePackets */
   7.237 +    //KdPrint((__DRIVER_NAME "     No free packets\n"));
   7.238 +    //FUNCTION_EXIT();
   7.239 +    return NULL;
   7.240 +  }
   7.241 +  
   7.242 +  header_buf = NdisAllocateFromNPagedLookasideList(&xi->rx_lookaside_list);
   7.243 +  if (!header_buf)
   7.244 +  {
   7.245 +    KdPrint((__DRIVER_NAME "     No free header buffers\n"));
   7.246 +    put_packet_on_freelist(xi, packet);
   7.247 +    return NULL;
   7.248 +  }
   7.249 +  header_va = (PUCHAR)(header_buf + 1);
   7.250 +  NdisZeroMemory(header_buf, sizeof(shared_buffer_t));
   7.251 +  NdisMoveMemory(header_va, pi->header, pi->header_length);
   7.252 +  //KdPrint((__DRIVER_NAME "     header_length = %d, current_lookahead = %d\n", pi->header_length, xi->current_lookahead));
   7.253 +  //KdPrint((__DRIVER_NAME "     ip4_header_length = %d\n", pi->ip4_header_length));
   7.254 +  //KdPrint((__DRIVER_NAME "     tcp_header_length = %d\n", pi->tcp_header_length));
   7.255 +  /* make sure we satisfy the lookahead requirement */
   7.256 +  
   7.257 +  if (pi->split_required)
   7.258 +  {
   7.259 +    /* for split packets we need to make sure the 'header' is no bigger than header+mss bytes */
   7.260 +    XenNet_BuildHeader(pi, header_va, min((ULONG)MAX_ETH_HEADER_LENGTH + pi->ip4_header_length + pi->tcp_header_length + pi->mss, MAX_ETH_HEADER_LENGTH + max(MIN_LOOKAHEAD_LENGTH, xi->current_lookahead)));
   7.261 +  }
   7.262 +  else
   7.263 +  {
   7.264 +    XenNet_BuildHeader(pi, header_va, max(MIN_LOOKAHEAD_LENGTH, xi->current_lookahead) + MAX_ETH_HEADER_LENGTH);
   7.265 +  }
   7.266 +  header_extra = pi->header_length - (MAX_ETH_HEADER_LENGTH + pi->ip4_header_length + pi->tcp_header_length);
   7.267 +  ASSERT(pi->header_length <= MAX_ETH_HEADER_LENGTH + MAX_LOOKAHEAD_LENGTH);
   7.268 +  NdisAllocateBuffer(&status, &out_buffer, xi->rx_buffer_pool, header_va, pi->header_length);
   7.269 +  if (status != STATUS_SUCCESS)
   7.270 +  {
   7.271 +    KdPrint((__DRIVER_NAME "     No free header buffers\n"));
   7.272 +    NdisFreeToNPagedLookasideList(&xi->rx_lookaside_list, header_buf);
   7.273 +    put_packet_on_freelist(xi, packet);
   7.274 +    return NULL;
   7.275 +  }
   7.276 +  NdisChainBufferAtBack(packet, out_buffer);
   7.277 +  *(shared_buffer_t **)&packet->MiniportReservedEx[0] = header_buf;
   7.278 +  header_buf->next = pi->curr_pb;
   7.279 +
   7.280 +  // TODO: if there are only a few bytes left on the first buffer then add them to the header buffer too... maybe
   7.281 +
   7.282 +  if (pi->split_required)
   7.283 +  {
   7.284 +    tcp_length = (USHORT)min(pi->mss, pi->tcp_remaining);
   7.285 +    new_ip4_length = (USHORT)(pi->ip4_header_length + pi->tcp_header_length + tcp_length);
   7.286 +    //KdPrint((__DRIVER_NAME "     new_ip4_length = %d\n", new_ip4_length));
   7.287 +    //KdPrint((__DRIVER_NAME "     this tcp_length = %d\n", tcp_length));
   7.288 +    SET_NET_USHORT(&header_va[XN_HDR_SIZE + 2], new_ip4_length);
   7.289 +    SET_NET_ULONG(&header_va[XN_HDR_SIZE + pi->ip4_header_length + 4], pi->tcp_seq);
   7.290 +    pi->tcp_seq += tcp_length;
   7.291 +    pi->tcp_remaining = (USHORT)(pi->tcp_remaining - tcp_length);
   7.292 +    /* part of the packet is already present in the header buffer for lookahead */
   7.293 +    out_remaining = tcp_length - header_extra;
   7.294 +    ASSERT((LONG)out_remaining >= 0);
   7.295 +  }
   7.296 +  else
   7.297 +  {
   7.298 +    out_remaining = pi->total_length - pi->header_length;
   7.299 +    ASSERT((LONG)out_remaining >= 0);
   7.300 +  }
   7.301 +  //KdPrint((__DRIVER_NAME "     before loop - out_remaining = %d\n", out_remaining));
   7.302 +
   7.303 +  NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_RESOURCES); /* for packets only containing a header buffer - see Indicate*/
   7.304 +  while (out_remaining != 0)
   7.305 +  {
   7.306 +    ULONG in_buffer_offset;
   7.307 +    ULONG in_buffer_length;
   7.308 +    ULONG out_length;
   7.309 +    
   7.310 +    NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS); /* packet contains additional buffers */
   7.311 +    //KdPrint((__DRIVER_NAME "     in loop - out_remaining = %d, curr_buffer = %p, curr_pb = %p\n", out_remaining, pi->curr_buffer, pi->curr_pb));
   7.312 +    if (!pi->curr_buffer || !pi->curr_pb)
   7.313 +    {
   7.314 +      KdPrint((__DRIVER_NAME "     out of buffers for packet\n"));
   7.315 +      KdPrint((__DRIVER_NAME "     out_remaining = %d, curr_buffer = %p, curr_pb = %p\n", out_remaining, pi->curr_buffer, pi->curr_pb));
   7.316 +      // TODO: free some stuff or we'll leak
   7.317 +      /* unchain buffers then free packet */
   7.318 +      return NULL;
   7.319 +    }
   7.320 +    NdisQueryBufferOffset(pi->curr_buffer, &in_buffer_offset, &in_buffer_length);
   7.321 +    out_length = min(out_remaining, in_buffer_length - pi->curr_mdl_offset);
   7.322 +    NdisCopyBuffer(&status, &out_buffer, xi->rx_buffer_pool, pi->curr_buffer, pi->curr_mdl_offset, out_length);
   7.323 +    ASSERT(status == STATUS_SUCCESS); //TODO: properly handle error
   7.324 +    NdisChainBufferAtBack(packet, out_buffer);
   7.325 +    ref_pb(xi, pi->curr_pb);
   7.326 +    pi->curr_mdl_offset = (USHORT)(pi->curr_mdl_offset + out_length);
   7.327 +    if (pi->curr_mdl_offset == in_buffer_length)
   7.328 +    {
   7.329 +      NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
   7.330 +      pi->curr_pb = pi->curr_pb->next;
   7.331 +      pi->curr_mdl_offset = 0;
   7.332 +    }
   7.333 +    out_remaining -= out_length;
   7.334 +  }
   7.335 +  if (pi->split_required)
   7.336 +  {
   7.337 +    XenNet_SumIpHeader(header_va, pi->ip4_header_length);
   7.338 +  }
   7.339 +  if (header_extra > 0)
   7.340 +    pi->header_length -= header_extra;
   7.341 +  ASSERT(*(shared_buffer_t **)&packet->MiniportReservedEx[0]);
   7.342 +  //FUNCTION_EXIT();
   7.343 +  return packet;
   7.344 +}
   7.345 +
   7.346 +/*
   7.347 + Windows appears to insist that the checksum on received packets is correct, and won't
   7.348 + believe us when we lie about it, which happens when the packet is generated on the
   7.349 + same bridge in Dom0. Doh!
   7.350 + This is only for TCP and UDP packets. IP checksums appear to be correct anyways.
   7.351 +*/
   7.352 +
   7.353 +static BOOLEAN
   7.354 +XenNet_SumPacketData(
   7.355 +  packet_info_t *pi,
   7.356 +  PNDIS_PACKET packet,
   7.357 +  BOOLEAN set_csum
   7.358 +)
   7.359 +{
   7.360 +  USHORT i;
   7.361 +  PUCHAR buffer;
   7.362 +  PMDL mdl;
   7.363 +  UINT total_length;
   7.364 +  UINT data_length;
   7.365 +  UINT buffer_length;
   7.366 +  USHORT buffer_offset;
   7.367 +  ULONG csum;
   7.368 +  PUSHORT csum_ptr;
   7.369 +  USHORT remaining;
   7.370 +  USHORT ip4_length;
   7.371 +  BOOLEAN csum_span = TRUE; /* when the USHORT to be checksummed spans a buffer */
   7.372 +  
   7.373 +  //FUNCTION_ENTER();
   7.374 +
   7.375 +  NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
   7.376 +  ASSERT(mdl);
   7.377 +
   7.378 +  ip4_length = GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 2]);
   7.379 +  data_length = ip4_length + XN_HDR_SIZE;
   7.380 +  
   7.381 +  if ((USHORT)data_length > total_length)
   7.382 +  {
   7.383 +    KdPrint((__DRIVER_NAME "     Size Mismatch %d (ip4_length + XN_HDR_SIZE) != %d (total_length)\n", ip4_length + XN_HDR_SIZE, total_length));
   7.384 +    return FALSE;
   7.385 +  }
   7.386 +
   7.387 +  switch (pi->ip_proto)
   7.388 +  {
   7.389 +  case 6:
   7.390 +    ASSERT(buffer_length >= (USHORT)(XN_HDR_SIZE + pi->ip4_header_length + 17));
   7.391 +    csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + pi->ip4_header_length + 16];
   7.392 +    break;
   7.393 +  case 17:
   7.394 +    ASSERT(buffer_length >= (USHORT)(XN_HDR_SIZE + pi->ip4_header_length + 7));
   7.395 +    csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + pi->ip4_header_length + 6];
   7.396 +    break;
   7.397 +  default:
   7.398 +    KdPrint((__DRIVER_NAME "     Don't know how to calc sum for IP Proto %d\n", pi->ip_proto));
   7.399 +    //FUNCTION_EXIT();
   7.400 +    return FALSE; // should never happen
   7.401 +  }
   7.402 +
   7.403 +  if (set_csum)  
   7.404 +    *csum_ptr = 0;
   7.405 +
   7.406 +  csum = 0;
   7.407 +  csum += GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 12]) + GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 14]); // src
   7.408 +  csum += GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 16]) + GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 18]); // dst
   7.409 +  csum += ((USHORT)buffer[XN_HDR_SIZE + 9]);
   7.410 +
   7.411 +  remaining = ip4_length - pi->ip4_header_length;
   7.412 +
   7.413 +  csum += remaining;
   7.414 +  
   7.415 +  csum_span = FALSE;
   7.416 +  buffer_offset = i = XN_HDR_SIZE + pi->ip4_header_length;
   7.417 +  while (i < data_length)
   7.418 +  {
   7.419 +    /* don't include the checksum field itself in the calculation */
   7.420 +    if ((pi->ip_proto == 6 && i == XN_HDR_SIZE + pi->ip4_header_length + 16) || (pi->ip_proto == 17 && i == XN_HDR_SIZE + pi->ip4_header_length + 6))
   7.421 +    {
   7.422 +      /* we know that this always happens in the header buffer so we are guaranteed the full two bytes */
   7.423 +      i += 2;
   7.424 +      buffer_offset += 2;
   7.425 +      continue;
   7.426 +    }
   7.427 +    if (csum_span)
   7.428 +    {
   7.429 +      /* the other half of the next bit */
   7.430 +      ASSERT(buffer_offset == 0);
   7.431 +      csum += (USHORT)buffer[buffer_offset];
   7.432 +      csum_span = FALSE;
   7.433 +      i += 1;
   7.434 +      buffer_offset += 1;
   7.435 +    }
   7.436 +    else if (buffer_offset == buffer_length - 1)
   7.437 +    {
   7.438 +      /* deal with a buffer ending on an odd byte boundary */
   7.439 +      csum += (USHORT)buffer[buffer_offset] << 8;
   7.440 +      csum_span = TRUE;
   7.441 +      i += 1;
   7.442 +      buffer_offset += 1;
   7.443 +    }
   7.444 +    else
   7.445 +    {
   7.446 +      csum += GET_NET_PUSHORT(&buffer[buffer_offset]);
   7.447 +      i += 2;
   7.448 +      buffer_offset += 2;
   7.449 +    }
   7.450 +    if (buffer_offset == buffer_length && i < total_length)
   7.451 +    {
   7.452 +      NdisGetNextBuffer(mdl, &mdl);
   7.453 +      if (mdl == NULL)
   7.454 +      {
   7.455 +        KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   7.456 +        return FALSE; // should never happen
   7.457 +      }
   7.458 +      NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
   7.459 +      ASSERT(buffer_length);
   7.460 +      buffer_offset = 0;
   7.461 +    }
   7.462 +  }
   7.463 +      
   7.464 +  while (csum & 0xFFFF0000)
   7.465 +    csum = (csum & 0xFFFF) + (csum >> 16);
   7.466 +  
   7.467 +  if (set_csum)
   7.468 +  {
   7.469 +    *csum_ptr = (USHORT)~GET_NET_USHORT((USHORT)csum);
   7.470 +  }
   7.471 +  else
   7.472 +  {
   7.473 +    //FUNCTION_EXIT();
   7.474 +    return (BOOLEAN)(*csum_ptr == (USHORT)~GET_NET_USHORT((USHORT)csum));
   7.475 +  }
   7.476 +  //FUNCTION_EXIT();
   7.477 +  return TRUE;
   7.478 +}
   7.479 +
   7.480 +static ULONG
   7.481 +XenNet_MakePackets(
   7.482 +  struct xennet_info *xi,
   7.483 +  PLIST_ENTRY rx_packet_list,
   7.484 +  packet_info_t *pi
   7.485 +)
   7.486 +{
   7.487 +  ULONG packet_count = 0;
   7.488 +  PNDIS_PACKET packet;
   7.489 +  PLIST_ENTRY entry;
   7.490 +  UCHAR psh;
   7.491 +  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   7.492 +  ULONG parse_result;  
   7.493 +  //PNDIS_BUFFER buffer;
   7.494 +  shared_buffer_t *page_buf;
   7.495 +
   7.496 +  //FUNCTION_ENTER();
   7.497 +
   7.498 +  parse_result = XenNet_ParsePacketHeader(pi, NULL, 0);
   7.499 +  
   7.500 +  if (!XenNet_FilterAcceptPacket(xi, pi))
   7.501 +  {
   7.502 +    goto done;
   7.503 +  }
   7.504 +
   7.505 +  switch (pi->ip_proto)
   7.506 +  {
   7.507 +  case 6:  // TCP
   7.508 +    if (pi->split_required)
   7.509 +      break;
   7.510 +    // fallthrough
   7.511 +  case 17:  // UDP
   7.512 +    packet = XenNet_MakePacket(xi, pi);
   7.513 +    if (packet == NULL)
   7.514 +    {
   7.515 +      //KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
   7.516 +      xi->stat_rx_no_buffer++;
   7.517 +      packet_count = 0;
   7.518 +      goto done;
   7.519 +    }
   7.520 +    if (parse_result == PARSE_OK)
   7.521 +    {
   7.522 +      BOOLEAN checksum_offload = FALSE;
   7.523 +      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   7.524 +        packet, TcpIpChecksumPacketInfo);
   7.525 +      ASSERT(csum_info->Value == 0);
   7.526 +      if (pi->csum_blank || pi->data_validated)
   7.527 +      {
   7.528 +        if (xi->setting_csum.V4Receive.TcpChecksum && pi->ip_proto == 6)
   7.529 +        {
   7.530 +          if (!pi->tcp_has_options || xi->setting_csum.V4Receive.TcpOptionsSupported)
   7.531 +          {
   7.532 +            csum_info->Receive.NdisPacketIpChecksumSucceeded = TRUE;
   7.533 +            csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   7.534 +            checksum_offload = TRUE;
   7.535 +          }
   7.536 +        }
   7.537 +        else if (xi->setting_csum.V4Receive.UdpChecksum && pi->ip_proto == 17)
   7.538 +        {
   7.539 +          csum_info->Receive.NdisPacketIpChecksumSucceeded = TRUE;
   7.540 +          csum_info->Receive.NdisPacketUdpChecksumSucceeded = TRUE;
   7.541 +          checksum_offload = TRUE;
   7.542 +        }
   7.543 +        if (pi->csum_blank && (!xi->config_csum_rx_dont_fix || !checksum_offload))
   7.544 +        {
   7.545 +          XenNet_SumPacketData(pi, packet, TRUE);
   7.546 +        }
   7.547 +      }
   7.548 +      else if (xi->config_csum_rx_check)
   7.549 +      {
   7.550 +        if (xi->setting_csum.V4Receive.TcpChecksum && pi->ip_proto == 6)
   7.551 +        {
   7.552 +          if (XenNet_SumPacketData(pi, packet, FALSE))
   7.553 +          {
   7.554 +            csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   7.555 +          }
   7.556 +          else
   7.557 +          {
   7.558 +            csum_info->Receive.NdisPacketTcpChecksumFailed = TRUE;
   7.559 +          }
   7.560 +        } else if (xi->setting_csum.V4Receive.UdpChecksum && pi->ip_proto == 17)
   7.561 +        {
   7.562 +          if (XenNet_SumPacketData(pi, packet, FALSE))
   7.563 +          {
   7.564 +            csum_info->Receive.NdisPacketUdpChecksumSucceeded = TRUE;
   7.565 +          }
   7.566 +          else
   7.567 +          {
   7.568 +            csum_info->Receive.NdisPacketUdpChecksumFailed = TRUE;
   7.569 +          }
   7.570 +        }
   7.571 +      }
   7.572 +    }
   7.573 +    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   7.574 +    InsertTailList(rx_packet_list, entry);
   7.575 +    packet_count = 1;
   7.576 +    goto done;
   7.577 +  default:
   7.578 +    packet = XenNet_MakePacket(xi, pi);
   7.579 +    if (packet == NULL)
   7.580 +    {
   7.581 +      //KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
   7.582 +      xi->stat_rx_no_buffer++;
   7.583 +      packet_count = 0;
   7.584 +      goto done;
   7.585 +    }
   7.586 +    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   7.587 +    InsertTailList(rx_packet_list, entry);
   7.588 +    packet_count = 1;
   7.589 +    goto done;
   7.590 +  }
   7.591 +  
   7.592 +  pi->tcp_remaining = pi->tcp_length;
   7.593 +
   7.594 +  /* we can make certain assumptions here as the following code is only for tcp4 */
   7.595 +  psh = pi->header[XN_HDR_SIZE + pi->ip4_header_length + 13] & 8;
   7.596 +  while (pi->tcp_remaining)
   7.597 +  {
   7.598 +    PUCHAR header_va;
   7.599 +    PMDL mdl;
   7.600 +    UINT total_length;
   7.601 +    UINT buffer_length;
   7.602 +    packet = XenNet_MakePacket(xi, pi);
   7.603 +    if (!packet)
   7.604 +    {
   7.605 +      //KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
   7.606 +      xi->stat_rx_no_buffer++;
   7.607 +      break; /* we are out of memory - just drop the packets */
   7.608 +    }
   7.609 +    if (xi->setting_csum.V4Receive.TcpChecksum)
   7.610 +    {
   7.611 +      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   7.612 +        packet, TcpIpChecksumPacketInfo);
   7.613 +      csum_info->Receive.NdisPacketIpChecksumSucceeded = TRUE;
   7.614 +      csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   7.615 +    }
   7.616 +    if (psh)
   7.617 +    {
   7.618 +      NdisGetFirstBufferFromPacketSafe(packet, &mdl, &header_va, &buffer_length, &total_length, NormalPagePriority);
   7.619 +      if (pi->tcp_remaining)
   7.620 +        header_va[XN_HDR_SIZE + pi->ip4_header_length + 13] &= ~8;
   7.621 +      else
   7.622 +        header_va[XN_HDR_SIZE + pi->ip4_header_length + 13] |= 8;
   7.623 +    }
   7.624 +    XenNet_SumPacketData(pi, packet, TRUE);
   7.625 +    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   7.626 +    InsertTailList(rx_packet_list, entry);
   7.627 +    packet_count++;
   7.628 +  }
   7.629 +
   7.630 +done:
   7.631 +  page_buf = pi->first_pb;
   7.632 +  while (page_buf)
   7.633 +  {
   7.634 +    shared_buffer_t *next_pb;
   7.635 +
   7.636 +    next_pb = page_buf->next;
   7.637 +    put_pb_on_freelist(xi, page_buf);
   7.638 +    page_buf = next_pb;
   7.639 +  }
   7.640 +  XenNet_ClearPacketInfo(pi);
   7.641 +  //FUNCTION_EXIT();
   7.642 +  return packet_count;
   7.643 +}
   7.644 +
   7.645 +
   7.646 +/* called at DISPATCH_LEVEL */
   7.647 +/* it's okay for return packet to be called while resume_state != RUNNING as the packet will simply be added back to the freelist, the grants will be fixed later */
   7.648 +VOID
   7.649 +XenNet_ReturnPacket(
   7.650 +  IN NDIS_HANDLE MiniportAdapterContext,
   7.651 +  IN PNDIS_PACKET Packet
   7.652 +  )
   7.653 +{
   7.654 +  struct xennet_info *xi = MiniportAdapterContext;
   7.655 +  PNDIS_BUFFER buffer;
   7.656 +  shared_buffer_t *page_buf = *(shared_buffer_t **)&Packet->MiniportReservedEx[0];
   7.657 +
   7.658 +  //FUNCTION_ENTER();
   7.659 +
   7.660 +  //KdPrint((__DRIVER_NAME "     page_buf = %p\n", page_buf));
   7.661 +
   7.662 +  NdisUnchainBufferAtFront(Packet, &buffer);
   7.663 +  
   7.664 +  while (buffer)
   7.665 +  {
   7.666 +    shared_buffer_t *next_buf;
   7.667 +    ASSERT(page_buf);
   7.668 +    next_buf = page_buf->next;
   7.669 +    if (!page_buf->virtual)
   7.670 +    {
   7.671 +      /* this isn't actually a share_buffer, it is some memory allocated for the header - just free it */
   7.672 +      PUCHAR va;
   7.673 +      UINT len;
   7.674 +      NdisQueryBufferSafe(buffer, &va, &len, NormalPagePriority);
   7.675 +      NdisFreeToNPagedLookasideList(&xi->rx_lookaside_list, va - sizeof(shared_buffer_t));
   7.676 +      NdisFreeBuffer(buffer);
   7.677 +    }
   7.678 +    else
   7.679 +    {
   7.680 +      //KdPrint((__DRIVER_NAME "     returning page_buf %p with id %d\n", page_buf, page_buf->id));
   7.681 +      if (buffer != page_buf->buffer)
   7.682 +        NdisFreeBuffer(buffer);
   7.683 +      put_pb_on_freelist(xi, page_buf);
   7.684 +    }
   7.685 +    NdisUnchainBufferAtFront(Packet, &buffer);
   7.686 +    page_buf = next_buf;
   7.687 +  }
   7.688 +
   7.689 +  put_packet_on_freelist(xi, Packet);
   7.690 +  InterlockedDecrement(&xi->rx_outstanding);
   7.691 +  
   7.692 +  if (!xi->rx_outstanding && xi->rx_shutting_down)
   7.693 +    KeSetEvent(&xi->packet_returned_event, IO_NO_INCREMENT, FALSE);
   7.694 +
   7.695 +#if 0 /* don't do this as it's called an awful lot */
   7.696 +  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
   7.697 +
   7.698 +  XenNet_FillRing(xi);
   7.699 +
   7.700 +  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   7.701 +#endif
   7.702 +  //FUNCTION_EXIT();
   7.703 +}
   7.704 +
   7.705 +#define MAXIMUM_PACKETS_PER_INDICATE 32
   7.706 +
   7.707 +/* We limit the number of packets per interrupt so that acks get a chance
   7.708 +under high rx load. The DPC is immediately re-scheduled */
   7.709 +#define MAXIMUM_PACKETS_PER_INTERRUPT 32 /* this is calculated before large packet split */
   7.710 +#define MAXIMUM_DATA_PER_INTERRUPT (MAXIMUM_PACKETS_PER_INTERRUPT * 1500) /* help account for large packets */
   7.711 +
   7.712 +// Called at DISPATCH_LEVEL
   7.713 +BOOLEAN
   7.714 +XenNet_RxBufferCheck(struct xennet_info *xi)
   7.715 +{
   7.716 +  RING_IDX cons, prod;
   7.717 +  LIST_ENTRY rx_packet_list;
   7.718 +  LIST_ENTRY rx_header_only_packet_list;
   7.719 +  PLIST_ENTRY entry;
   7.720 +  PNDIS_PACKET packets[MAXIMUM_PACKETS_PER_INDICATE];
   7.721 +  ULONG packet_count = 0;
   7.722 +  ULONG buffer_count = 0;
   7.723 +  ULONG packet_data = 0;
   7.724 +  ULONG interim_packet_data = 0;
   7.725 +  struct netif_extra_info *ei;
   7.726 +  USHORT id;
   7.727 +  int more_to_do = FALSE;
   7.728 +  packet_info_t *pi = &xi->rxpi[KeGetCurrentProcessorNumber() & 0xff];
   7.729 +  shared_buffer_t *page_buf;
   7.730 +  shared_buffer_t *head_buf = NULL;
   7.731 +  shared_buffer_t *tail_buf = NULL;
   7.732 +  shared_buffer_t *last_buf = NULL;
   7.733 +  BOOLEAN extra_info_flag = FALSE;
   7.734 +  BOOLEAN more_data_flag = FALSE;
   7.735 +  PNDIS_BUFFER buffer;
   7.736 +  BOOLEAN dont_set_event;
   7.737 +
   7.738 +  //FUNCTION_ENTER();
   7.739 +
   7.740 +  if (!xi->connected)
   7.741 +    return FALSE; /* a delayed DPC could let this come through... just do nothing */
   7.742 +
   7.743 +  InitializeListHead(&rx_packet_list);
   7.744 +
   7.745 +  /* get all the buffers off the ring as quickly as possible so the lock is held for a minimum amount of time */
   7.746 +
   7.747 +  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
   7.748 +  
   7.749 +  if (xi->rx_shutting_down)
   7.750 +  {
   7.751 +    /* there is a chance that our Dpc had been queued just before the shutdown... */
   7.752 +    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   7.753 +    return FALSE;
   7.754 +  }
   7.755 +
   7.756 +  if (xi->rx_partial_buf)
   7.757 +  {
   7.758 +    head_buf = xi->rx_partial_buf;
   7.759 +    tail_buf = xi->rx_partial_buf;
   7.760 +    while (tail_buf->next)
   7.761 +      tail_buf = tail_buf->next;
   7.762 +    more_data_flag = xi->rx_partial_more_data_flag;
   7.763 +    extra_info_flag = xi->rx_partial_extra_info_flag;
   7.764 +    xi->rx_partial_buf = NULL;
   7.765 +  }
   7.766 +
   7.767 +  do {
   7.768 +    prod = xi->rx.sring->rsp_prod;
   7.769 +    KeMemoryBarrier(); /* Ensure we see responses up to 'prod'. */
   7.770 +
   7.771 +    for (cons = xi->rx.rsp_cons; cons != prod && packet_count < MAXIMUM_PACKETS_PER_INTERRUPT && packet_data < MAXIMUM_DATA_PER_INTERRUPT; cons++)
   7.772 +    {
   7.773 +      id = (USHORT)(cons & (NET_RX_RING_SIZE - 1));
   7.774 +      page_buf = xi->rx_ring_pbs[id];
   7.775 +      ASSERT(page_buf);
   7.776 +      xi->rx_ring_pbs[id] = NULL;
   7.777 +      xi->rx_id_free++;
   7.778 +      memcpy(&page_buf->rsp, RING_GET_RESPONSE(&xi->rx, cons), max(sizeof(struct netif_rx_response), sizeof(struct netif_extra_info)));
   7.779 +      if (!extra_info_flag)
   7.780 +      {
   7.781 +        if (page_buf->rsp.status <= 0
   7.782 +          || page_buf->rsp.offset + page_buf->rsp.status > PAGE_SIZE)
   7.783 +        {
   7.784 +          KdPrint((__DRIVER_NAME "     Error: rsp offset %d, size %d\n",
   7.785 +            page_buf->rsp.offset, page_buf->rsp.status));
   7.786 +          ASSERT(!extra_info_flag);
   7.787 +          put_pb_on_freelist(xi, page_buf);
   7.788 +          continue;
   7.789 +        }
   7.790 +      }
   7.791 +      
   7.792 +      if (!head_buf)
   7.793 +      {
   7.794 +        head_buf = page_buf;
   7.795 +        tail_buf = page_buf;
   7.796 +      }
   7.797 +      else
   7.798 +      {
   7.799 +        tail_buf->next = page_buf;
   7.800 +        tail_buf = page_buf;
   7.801 +      }
   7.802 +      page_buf->next = NULL;
   7.803 +
   7.804 +      if (extra_info_flag)
   7.805 +      {
   7.806 +        ei = (struct netif_extra_info *)&page_buf->rsp;
   7.807 +        extra_info_flag = ei->flags & XEN_NETIF_EXTRA_FLAG_MORE;
   7.808 +      }
   7.809 +      else
   7.810 +      {
   7.811 +        more_data_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_more_data);
   7.812 +        extra_info_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_extra_info);
   7.813 +        interim_packet_data += page_buf->rsp.status;
   7.814 +      }
   7.815 +      
   7.816 +      if (!extra_info_flag && !more_data_flag)
   7.817 +      {
   7.818 +        last_buf = page_buf;
   7.819 +        packet_count++;
   7.820 +        packet_data += interim_packet_data;
   7.821 +        interim_packet_data = 0;
   7.822 +      }
   7.823 +      buffer_count++;
   7.824 +    }
   7.825 +    xi->rx.rsp_cons = cons;
   7.826 +
   7.827 +    /* Give netback more buffers */
   7.828 +    XenNet_FillRing(xi);
   7.829 +
   7.830 +    if (packet_count >= MAXIMUM_PACKETS_PER_INTERRUPT || packet_data >= MAXIMUM_DATA_PER_INTERRUPT)
   7.831 +      break;
   7.832 +
   7.833 +    more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xi->rx);
   7.834 +    if (!more_to_do)
   7.835 +    {
   7.836 +      xi->rx.sring->rsp_event = xi->rx.rsp_cons + 1;
   7.837 +      KeMemoryBarrier();
   7.838 +      more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xi->rx);
   7.839 +    }
   7.840 +  } while (more_to_do);
   7.841 +  
   7.842 +  /* anything past last_buf belongs to an incomplete packet... */
   7.843 +  if (last_buf && last_buf->next)
   7.844 +  {
   7.845 +    KdPrint((__DRIVER_NAME "     Partial receive\n"));
   7.846 +    xi->rx_partial_buf = last_buf->next;
   7.847 +    xi->rx_partial_more_data_flag = more_data_flag;
   7.848 +    xi->rx_partial_extra_info_flag = extra_info_flag;
   7.849 +    last_buf->next = NULL;
   7.850 +  }
   7.851 +
   7.852 +  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   7.853 +
   7.854 +  if (packet_count >= MAXIMUM_PACKETS_PER_INTERRUPT || packet_data >= MAXIMUM_DATA_PER_INTERRUPT)
   7.855 +  {
   7.856 +    /* fire again immediately */
   7.857 +    //KdPrint((__DRIVER_NAME "     Dpc Duration Exceeded\n"));
   7.858 +    dpc_limit_hit++;
   7.859 +    /* we want the Dpc on the end of the queue. By definition we are already on the right CPU so we know the Dpc queue will be run immediately */
   7.860 +    KeSetImportanceDpc(&xi->rxtx_dpc, MediumImportance);
   7.861 +    KeInsertQueueDpc(&xi->rxtx_dpc, NULL, NULL);
   7.862 +    /* dont set an event in TX path */
   7.863 +    dont_set_event = TRUE;
   7.864 +  }
   7.865 +  else
   7.866 +  {
   7.867 +    /* make sure the Dpc queue is run immediately next interrupt */
   7.868 +    KeSetImportanceDpc(&xi->rxtx_dpc, HighImportance);
   7.869 +    /* set an event in TX path */
   7.870 +    dont_set_event = FALSE;
   7.871 +  }
   7.872 +
   7.873 +  /* make packets out of the buffers */
   7.874 +  page_buf = head_buf;
   7.875 +  extra_info_flag = FALSE;
   7.876 +  more_data_flag = FALSE;
   7.877 +  while (page_buf)
   7.878 +  {
   7.879 +    shared_buffer_t *next_buf = page_buf->next;
   7.880 +
   7.881 +    page_buf->next = NULL;
   7.882 +    if (extra_info_flag)
   7.883 +    {
   7.884 +      //KdPrint((__DRIVER_NAME "     processing extra info\n"));
   7.885 +      ei = (struct netif_extra_info *)&page_buf->rsp;
   7.886 +      extra_info_flag = ei->flags & XEN_NETIF_EXTRA_FLAG_MORE;
   7.887 +      switch (ei->type)
   7.888 +      {
   7.889 +      case XEN_NETIF_EXTRA_TYPE_GSO:
   7.890 +        switch (ei->u.gso.type)
   7.891 +        {
   7.892 +        case XEN_NETIF_GSO_TYPE_TCPV4:
   7.893 +          pi->mss = ei->u.gso.size;
   7.894 +          //KdPrint((__DRIVER_NAME "     mss = %d\n", pi->mss));
   7.895 +          // TODO - put this assertion somewhere ASSERT(header_len + pi->mss <= PAGE_SIZE); // this limits MTU to PAGE_SIZE - XN_HEADER_LEN
   7.896 +          break;
   7.897 +        default:
   7.898 +          KdPrint((__DRIVER_NAME "     Unknown GSO type (%d) detected\n", ei->u.gso.type));
   7.899 +          break;
   7.900 +        }
   7.901 +        break;
   7.902 +      default:
   7.903 +        KdPrint((__DRIVER_NAME "     Unknown extra info type (%d) detected\n", ei->type));
   7.904 +        break;
   7.905 +      }
   7.906 +      put_pb_on_freelist(xi, page_buf);
   7.907 +    }
   7.908 +    else
   7.909 +    {
   7.910 +      ASSERT(!page_buf->rsp.offset);
   7.911 +      if (!more_data_flag) // handling the packet's 1st buffer
   7.912 +      {
   7.913 +        if (page_buf->rsp.flags & NETRXF_csum_blank)
   7.914 +          pi->csum_blank = TRUE;
   7.915 +        if (page_buf->rsp.flags & NETRXF_data_validated)
   7.916 +          pi->data_validated = TRUE;
   7.917 +      }
   7.918 +      buffer = page_buf->buffer;
   7.919 +      NdisAdjustBufferLength(buffer, page_buf->rsp.status);
   7.920 +      //KdPrint((__DRIVER_NAME "     buffer = %p, pb = %p\n", buffer, page_buf));
   7.921 +      if (pi->first_pb)
   7.922 +      {
   7.923 +        ASSERT(pi->curr_pb);
   7.924 +        //KdPrint((__DRIVER_NAME "     additional buffer\n"));
   7.925 +        pi->curr_pb->next = page_buf;
   7.926 +        pi->curr_pb = page_buf;
   7.927 +        ASSERT(pi->curr_buffer);
   7.928 +        NDIS_BUFFER_LINKAGE(pi->curr_buffer) = buffer;
   7.929 +        pi->curr_buffer = buffer;
   7.930 +      }
   7.931 +      else
   7.932 +      {
   7.933 +        pi->first_pb = page_buf;
   7.934 +        pi->curr_pb = page_buf;
   7.935 +        pi->first_buffer = buffer;
   7.936 +        pi->curr_buffer = buffer;
   7.937 +      }
   7.938 +      pi->mdl_count++;
   7.939 +      extra_info_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_extra_info);
   7.940 +      more_data_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_more_data);
   7.941 +      pi->total_length = pi->total_length + page_buf->rsp.status;
   7.942 +    }
   7.943 +
   7.944 +    /* Packet done, add it to the list */
   7.945 +    if (!more_data_flag && !extra_info_flag)
   7.946 +    {
   7.947 +      pi->curr_pb = pi->first_pb;
   7.948 +      pi->curr_buffer = pi->first_buffer;
   7.949 +      XenNet_MakePackets(xi, &rx_packet_list, pi);
   7.950 +    }
   7.951 +
   7.952 +    page_buf = next_buf;
   7.953 +  }
   7.954 +  ASSERT(!more_data_flag && !extra_info_flag);
   7.955 +      
   7.956 +  xi->stat_rx_ok += packet_count;
   7.957 +
   7.958 +  /* indicate packets to NDIS */
   7.959 +  entry = RemoveHeadList(&rx_packet_list);
   7.960 +  InitializeListHead(&rx_header_only_packet_list);
   7.961 +  packet_count = 0;
   7.962 +
   7.963 +  while (entry != &rx_packet_list) {
   7.964 +    PNDIS_PACKET packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   7.965 +    NDIS_STATUS status;
   7.966 +    ASSERT(*(shared_buffer_t **)&packet->MiniportReservedEx[0]);
   7.967 +    status = NDIS_GET_PACKET_STATUS(packet);
   7.968 +    if (status == NDIS_STATUS_RESOURCES)
   7.969 +      InsertTailList(&rx_header_only_packet_list, entry);
   7.970 +    packets[packet_count++] = packet;
   7.971 +    InterlockedIncrement(&xi->rx_outstanding);
   7.972 +    entry = RemoveHeadList(&rx_packet_list);
   7.973 +    /* if we indicate a packet with NDIS_STATUS_RESOURCES  then any following packet can't be NDIS_STATUS_SUCCESS */
   7.974 +    if (packet_count == MAXIMUM_PACKETS_PER_INDICATE || entry == &rx_packet_list
   7.975 +        || (NDIS_GET_PACKET_STATUS(CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)])) == NDIS_STATUS_SUCCESS
   7.976 +            && status == NDIS_STATUS_RESOURCES))
   7.977 +    {
   7.978 +      NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
   7.979 +      packet_count = 0;
   7.980 +    }
   7.981 +  }
   7.982 +  /* now return the packets for which we indicated NDIS_STATUS_RESOURCES */
   7.983 +  entry = RemoveHeadList(&rx_header_only_packet_list);
   7.984 +  while (entry != &rx_header_only_packet_list) {
   7.985 +    PNDIS_PACKET packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   7.986 +    entry = RemoveHeadList(&rx_header_only_packet_list);
   7.987 +    InterlockedIncrement(&resource_packets);
   7.988 +    XenNet_ReturnPacket(xi, packet);
   7.989 +  }
   7.990 +  return dont_set_event;
   7.991 +  //FUNCTION_EXIT();
   7.992 +}
   7.993 +
   7.994 +/*
   7.995 +   Free all Rx buffers (on halt, for example) 
   7.996 +   The ring must be stopped at this point.
   7.997 +*/
   7.998 +
   7.999 +static VOID
  7.1000 +XenNet_PurgeRing(struct xennet_info *xi)
  7.1001 +{
  7.1002 +  int i;
  7.1003 +  for (i = 0; i < NET_RX_RING_SIZE; i++)
  7.1004 +  {
  7.1005 +    if (xi->rx_ring_pbs[i] != NULL)
  7.1006 +    {
  7.1007 +      put_pb_on_freelist(xi, xi->rx_ring_pbs[i]);
  7.1008 +      xi->rx_ring_pbs[i] = NULL;
  7.1009 +    }
  7.1010 +  }
  7.1011 +}
  7.1012 +
  7.1013 +static VOID
  7.1014 +XenNet_BufferFree(struct xennet_info *xi)
  7.1015 +{
  7.1016 +  shared_buffer_t *pb;
  7.1017 +
  7.1018 +  XenNet_PurgeRing(xi);
  7.1019 +
  7.1020 +  while ((pb = get_pb_from_freelist(xi)) != NULL)
  7.1021 +  {
  7.1022 +    NdisFreeBuffer(pb->buffer);
  7.1023 +    xi->vectors.GntTbl_EndAccess(xi->vectors.context,
  7.1024 +        pb->gref, FALSE, (ULONG)'XNRX');
  7.1025 +    NdisFreeMemory(pb->virtual, PAGE_SIZE, 0);
  7.1026 +    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
  7.1027 +  }
  7.1028 +}
  7.1029 +
  7.1030 +VOID
  7.1031 +XenNet_RxResumeStart(xennet_info_t *xi)
  7.1032 +{
  7.1033 +  KIRQL old_irql;
  7.1034 +
  7.1035 +  FUNCTION_ENTER();
  7.1036 +
  7.1037 +  KeAcquireSpinLock(&xi->rx_lock, &old_irql);
  7.1038 +  XenNet_PurgeRing(xi);
  7.1039 +  KeReleaseSpinLock(&xi->rx_lock, old_irql);
  7.1040 +  
  7.1041 +  FUNCTION_EXIT();
  7.1042 +}
  7.1043 +
  7.1044 +VOID
  7.1045 +XenNet_BufferAlloc(xennet_info_t *xi)
  7.1046 +{
  7.1047 +  //NDIS_STATUS status;
  7.1048 +  int i;
  7.1049 +  
  7.1050 +  xi->rx_id_free = NET_RX_RING_SIZE;
  7.1051 +  xi->rx_outstanding = 0;
  7.1052 +
  7.1053 +  for (i = 0; i < NET_RX_RING_SIZE; i++)
  7.1054 +  {
  7.1055 +    xi->rx_ring_pbs[i] = NULL;
  7.1056 +  }
  7.1057 +}
  7.1058 +
  7.1059 +VOID
  7.1060 +XenNet_RxResumeEnd(xennet_info_t *xi)
  7.1061 +{
  7.1062 +  KIRQL old_irql;
  7.1063 +
  7.1064 +  FUNCTION_ENTER();
  7.1065 +
  7.1066 +  KeAcquireSpinLock(&xi->rx_lock, &old_irql);
  7.1067 +  //XenNet_BufferAlloc(xi);
  7.1068 +  XenNet_FillRing(xi);
  7.1069 +  KeReleaseSpinLock(&xi->rx_lock, old_irql);
  7.1070 +  
  7.1071 +  FUNCTION_EXIT();
  7.1072 +}
  7.1073 +
  7.1074 +BOOLEAN
  7.1075 +XenNet_RxInit(xennet_info_t *xi)
  7.1076 +{
  7.1077 +  NDIS_STATUS status;
  7.1078 +
  7.1079 +  FUNCTION_ENTER();
  7.1080 +
  7.1081 +  xi->rx_shutting_down = FALSE;
  7.1082 +  KeInitializeSpinLock(&xi->rx_lock);
  7.1083 +  KeInitializeEvent(&xi->packet_returned_event, SynchronizationEvent, FALSE);
  7.1084 +  KeInitializeTimer(&xi->rx_timer);
  7.1085 +  status = NdisAllocateMemoryWithTag((PVOID)&xi->rxpi, sizeof(packet_info_t) * NdisSystemProcessorCount(), XENNET_POOL_TAG);
  7.1086 +  if (status != NDIS_STATUS_SUCCESS)
  7.1087 +  {
  7.1088 +    KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
  7.1089 +    return FALSE;
  7.1090 +  }
  7.1091 +  NdisZeroMemory(xi->rxpi, sizeof(packet_info_t) * NdisSystemProcessorCount());
  7.1092 +
  7.1093 +  stack_new(&xi->rx_pb_stack, NET_RX_RING_SIZE * 4);
  7.1094 +
  7.1095 +  XenNet_BufferAlloc(xi);
  7.1096 +  
  7.1097 +  NdisAllocatePacketPool(&status, &xi->rx_packet_pool, NET_RX_RING_SIZE * 4,
  7.1098 +    PROTOCOL_RESERVED_SIZE_IN_PACKET);
  7.1099 +  if (status != NDIS_STATUS_SUCCESS)
  7.1100 +  {
  7.1101 +    KdPrint(("NdisAllocatePacketPool failed with 0x%x\n", status));
  7.1102 +    return FALSE;
  7.1103 +  }
  7.1104 +  stack_new(&xi->rx_packet_stack, NET_RX_RING_SIZE * 4);
  7.1105 +
  7.1106 +  NdisInitializeNPagedLookasideList(&xi->rx_lookaside_list, NULL, NULL, 0,
  7.1107 +    MAX_ETH_HEADER_LENGTH + MAX_LOOKAHEAD_LENGTH + sizeof(shared_buffer_t), XENNET_POOL_TAG, 0);
  7.1108 +  
  7.1109 +  XenNet_FillRing(xi);
  7.1110 +
  7.1111 +  FUNCTION_EXIT();
  7.1112 +
  7.1113 +  return TRUE;
  7.1114 +}
  7.1115 +
  7.1116 +BOOLEAN
  7.1117 +XenNet_RxShutdown(xennet_info_t *xi)
  7.1118 +{
  7.1119 +  KIRQL old_irql;
  7.1120 +  PNDIS_PACKET packet;
  7.1121 +
  7.1122 +  FUNCTION_ENTER();
  7.1123 +
  7.1124 +  KeAcquireSpinLock(&xi->rx_lock, &old_irql);
  7.1125 +  xi->rx_shutting_down = TRUE;
  7.1126 +  KeReleaseSpinLock(&xi->rx_lock, old_irql);
  7.1127 +
  7.1128 +  if (xi->config_rx_interrupt_moderation)
  7.1129 +  {
  7.1130 +    KeCancelTimer(&xi->rx_timer);
  7.1131 +  }
  7.1132 +
  7.1133 +#if (NTDDI_VERSION >= NTDDI_WINXP)
  7.1134 +  KeFlushQueuedDpcs();
  7.1135 +#endif
  7.1136 +
  7.1137 +  while (xi->rx_outstanding)
  7.1138 +  {
  7.1139 +    KdPrint((__DRIVER_NAME "     Waiting for all packets to be returned\n"));
  7.1140 +    KeWaitForSingleObject(&xi->packet_returned_event, Executive, KernelMode, FALSE, NULL);
  7.1141 +  }
  7.1142 +
  7.1143 +  //KeAcquireSpinLock(&xi->rx_lock, &old_irql);
  7.1144 +
  7.1145 +  NdisFreeMemory(xi->rxpi, sizeof(packet_info_t) * NdisSystemProcessorCount(), 0);
  7.1146 +
  7.1147 +  XenNet_BufferFree(xi);
  7.1148 +
  7.1149 +  /* this works because get_packet_from_freelist won't allocate new packets when rx_shutting_down */
  7.1150 +  while ((packet = get_packet_from_freelist(xi)) != NULL)
  7.1151 +    NdisFreePacket(packet);
  7.1152 +  stack_delete(xi->rx_packet_stack, NULL, NULL);
  7.1153 +  NdisFreePacketPool(xi->rx_packet_pool);
  7.1154 +
  7.1155 +  NdisDeleteNPagedLookasideList(&xi->rx_lookaside_list);
  7.1156 +
  7.1157 +  stack_delete(xi->rx_pb_stack, NULL, NULL);
  7.1158 +  //KeReleaseSpinLock(&xi->rx_lock, old_irql);
  7.1159 +
  7.1160 +  FUNCTION_EXIT();
  7.1161 +
  7.1162 +  return TRUE;
  7.1163 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xennet/xennet5_tx.c	Sat Apr 30 10:57:23 2011 +1000
     8.3 @@ -0,0 +1,715 @@
     8.4 +/*
     8.5 +PV Net Driver for Windows Xen HVM Domains
     8.6 +Copyright (C) 2007 James Harper
     8.7 +Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     8.8 +
     8.9 +This program is free software; you can redistribute it and/or
    8.10 +modify it under the terms of the GNU General Public License
    8.11 +as published by the Free Software Foundation; either version 2
    8.12 +of the License, or (at your option) any later version.
    8.13 +
    8.14 +This program is distributed in the hope that it will be useful,
    8.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.17 +GNU General Public License for more details.
    8.18 +
    8.19 +You should have received a copy of the GNU General Public License
    8.20 +along with this program; if not, write to the Free Software
    8.21 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    8.22 +*/
    8.23 +
    8.24 +#include "xennet5.h"
    8.25 +
    8.26 +static USHORT
    8.27 +get_id_from_freelist(struct xennet_info *xi)
    8.28 +{
    8.29 +  ASSERT(xi->tx_id_free);
    8.30 +  xi->tx_id_free--;
    8.31 +
    8.32 +  return xi->tx_id_list[xi->tx_id_free];
    8.33 +}
    8.34 +
    8.35 +static VOID
    8.36 +put_id_on_freelist(struct xennet_info *xi, USHORT id)
    8.37 +{
    8.38 +  xi->tx_id_list[xi->tx_id_free] = id;
    8.39 +  xi->tx_id_free++;
    8.40 +}
    8.41 +
    8.42 +#define SWAP_USHORT(x) (USHORT)((((x & 0xFF) << 8)|((x >> 8) & 0xFF)))
    8.43 +
    8.44 +static __forceinline struct netif_tx_request *
    8.45 +XenNet_PutCbOnRing(struct xennet_info *xi, PVOID coalesce_buf, ULONG length, grant_ref_t gref)
    8.46 +{
    8.47 +  struct netif_tx_request *tx;
    8.48 +  tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
    8.49 +  xi->tx.req_prod_pvt++;
    8.50 +  xi->tx_ring_free--;
    8.51 +  tx->id = get_id_from_freelist(xi);
    8.52 +  ASSERT(xi->tx_shadows[tx->id].gref == INVALID_GRANT_REF);
    8.53 +  ASSERT(!xi->tx_shadows[tx->id].cb);
    8.54 +  xi->tx_shadows[tx->id].cb = coalesce_buf;
    8.55 +  tx->gref = xi->vectors.GntTbl_GrantAccess(xi->vectors.context, 0, (ULONG)(MmGetPhysicalAddress(coalesce_buf).QuadPart >> PAGE_SHIFT), FALSE, gref, (ULONG)'XNTX');
    8.56 +  xi->tx_shadows[tx->id].gref = tx->gref;
    8.57 +  tx->offset = 0;
    8.58 +  tx->size = (USHORT)length;
    8.59 +  ASSERT(tx->offset + tx->size <= PAGE_SIZE);
    8.60 +  ASSERT(tx->size);
    8.61 +  return tx;
    8.62 +}
    8.63 +  
    8.64 +/* Called at DISPATCH_LEVEL with tx_lock held */
    8.65 +/*
    8.66 + * Send one NDIS_PACKET. This may involve multiple entries on TX ring.
    8.67 + */
    8.68 +static BOOLEAN
    8.69 +XenNet_HWSendPacket(struct xennet_info *xi, PNDIS_PACKET packet)
    8.70 +{
    8.71 +  struct netif_tx_request *tx0 = NULL;
    8.72 +  struct netif_tx_request *txN = NULL;
    8.73 +  struct netif_extra_info *ei = NULL;
    8.74 +  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    8.75 +  ULONG mss = 0;
    8.76 +  uint16_t flags = NETTXF_more_data;
    8.77 +  packet_info_t pi;
    8.78 +  BOOLEAN ndis_lso = FALSE;
    8.79 +  BOOLEAN xen_gso = FALSE;
    8.80 +  ULONG remaining;
    8.81 +  ULONG parse_result;
    8.82 +  ULONG frags = 0;
    8.83 +  BOOLEAN coalesce_required = FALSE;
    8.84 +  PVOID coalesce_buf;
    8.85 +  ULONG coalesce_remaining = 0;
    8.86 +  grant_ref_t gref;
    8.87 +  ULONG tx_length = 0;
    8.88 +  
    8.89 +  //FUNCTION_ENTER();
    8.90 +
    8.91 +  gref = xi->vectors.GntTbl_GetRef(xi->vectors.context, (ULONG)'XNTX');
    8.92 +  if (gref == INVALID_GRANT_REF)
    8.93 +  {
    8.94 +    KdPrint((__DRIVER_NAME "     out of grefs\n"));
    8.95 +    return FALSE;
    8.96 +  }
    8.97 +  coalesce_buf = NdisAllocateFromNPagedLookasideList(&xi->tx_lookaside_list);
    8.98 +  if (!coalesce_buf)
    8.99 +  {
   8.100 +    xi->vectors.GntTbl_PutRef(xi->vectors.context, gref, (ULONG)'XNTX');
   8.101 +    KdPrint((__DRIVER_NAME "     out of memory\n"));
   8.102 +    return FALSE;
   8.103 +  }
   8.104 +  XenNet_ClearPacketInfo(&pi);
   8.105 +  NdisQueryPacket(packet, NULL, (PUINT)&pi.mdl_count, &pi.first_buffer, (PUINT)&pi.total_length);
   8.106 +  
   8.107 +  pi.curr_mdl_offset = 0;
   8.108 +  pi.curr_buffer = pi.first_buffer;
   8.109 +  remaining = min(pi.total_length, PAGE_SIZE);
   8.110 +  while (remaining) /* this much gets put in the header */
   8.111 +  {
   8.112 +    ULONG length = XenNet_QueryData(&pi, remaining);
   8.113 +    remaining -= length;
   8.114 +    XenNet_EatData(&pi, length);
   8.115 +  }
   8.116 +  frags++;
   8.117 +  if (pi.total_length > PAGE_SIZE) /* these are the frags we care about */
   8.118 +  {
   8.119 +    remaining = pi.total_length - PAGE_SIZE;
   8.120 +    while (remaining)
   8.121 +    {
   8.122 +      ULONG length = XenNet_QueryData(&pi, PAGE_SIZE);
   8.123 +      if (length != 0)
   8.124 +      {
   8.125 +        frags++;
   8.126 +        if (frags > LINUX_MAX_SG_ELEMENTS)
   8.127 +          break; /* worst case there could be hundreds of fragments - leave the loop now */
   8.128 +      }
   8.129 +      remaining -= length;
   8.130 +      XenNet_EatData(&pi, length);
   8.131 +    }
   8.132 +  }
   8.133 +  if (frags > LINUX_MAX_SG_ELEMENTS)
   8.134 +  {
   8.135 +    frags = LINUX_MAX_SG_ELEMENTS;
   8.136 +    coalesce_required = TRUE;
   8.137 +  }
   8.138 +
   8.139 +  /* if we have enough space on the ring then we have enough id's so no need to check for that */
   8.140 +  if (xi->tx_ring_free < frags + 1)
   8.141 +  {
   8.142 +    xi->vectors.GntTbl_PutRef(xi->vectors.context, gref, (ULONG)'XNTX');
   8.143 +    NdisFreeToNPagedLookasideList(&xi->tx_lookaside_list, coalesce_buf);
   8.144 +    //KdPrint((__DRIVER_NAME "     Full on send - ring full\n"));
   8.145 +    return FALSE;
   8.146 +  }
   8.147 +  
   8.148 +  parse_result = XenNet_ParsePacketHeader(&pi, coalesce_buf, PAGE_SIZE);
   8.149 +  remaining = pi.total_length - pi.header_length;
   8.150 +
   8.151 +  if (NDIS_GET_PACKET_PROTOCOL_TYPE(packet) == NDIS_PROTOCOL_ID_TCP_IP)
   8.152 +  {
   8.153 +    csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   8.154 +      packet, TcpIpChecksumPacketInfo);
   8.155 +    if (csum_info->Transmit.NdisPacketChecksumV4)
   8.156 +    {
   8.157 +      if (csum_info->Transmit.NdisPacketIpChecksum && !xi->setting_csum.V4Transmit.IpChecksum)
   8.158 +      {
   8.159 +        KdPrint((__DRIVER_NAME "     IpChecksum not enabled\n"));
   8.160 +        //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
   8.161 +        //return TRUE;
   8.162 +      }
   8.163 +      if (csum_info->Transmit.NdisPacketTcpChecksum)
   8.164 +      {
   8.165 +        if (xi->setting_csum.V4Transmit.TcpChecksum)
   8.166 +        {
   8.167 +          flags |= NETTXF_csum_blank | NETTXF_data_validated;
   8.168 +        }
   8.169 +        else
   8.170 +        {
   8.171 +          KdPrint((__DRIVER_NAME "     TcpChecksum not enabled\n"));
   8.172 +          //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
   8.173 +          //return TRUE;
   8.174 +        }
   8.175 +      }
   8.176 +      else if (csum_info->Transmit.NdisPacketUdpChecksum)
   8.177 +      {
   8.178 +        if (xi->setting_csum.V4Transmit.UdpChecksum)
   8.179 +        {
   8.180 +          flags |= NETTXF_csum_blank | NETTXF_data_validated;
   8.181 +        }
   8.182 +        else
   8.183 +        {
   8.184 +          KdPrint((__DRIVER_NAME "     UdpChecksum not enabled\n"));
   8.185 +          //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
   8.186 +          //return TRUE;
   8.187 +        }
   8.188 +      }
   8.189 +    }
   8.190 +    else if (csum_info->Transmit.NdisPacketChecksumV6)
   8.191 +    {
   8.192 +      KdPrint((__DRIVER_NAME "     NdisPacketChecksumV6 not supported\n"));
   8.193 +      //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
   8.194 +      //return TRUE;
   8.195 +    }
   8.196 +  }
   8.197 +  
   8.198 +  mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
   8.199 +
   8.200 +  if (mss && parse_result == PARSE_OK)
   8.201 +  {
   8.202 +    if (NDIS_GET_PACKET_PROTOCOL_TYPE(packet) != NDIS_PROTOCOL_ID_TCP_IP)
   8.203 +    {
   8.204 +      KdPrint((__DRIVER_NAME "     mss specified when packet is not NDIS_PROTOCOL_ID_TCP_IP\n"));
   8.205 +    }
   8.206 +    ndis_lso = TRUE;
   8.207 +    if (mss > xi->setting_max_offload)
   8.208 +    {
   8.209 +      KdPrint((__DRIVER_NAME "     Requested MSS (%d) larger than allowed MSS (%d)\n", mss, xi->setting_max_offload));
   8.210 +      //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
   8.211 +      //FUNCTION_EXIT();
   8.212 +      return TRUE;
   8.213 +    }
   8.214 +  }
   8.215 +
   8.216 +  if (ndis_lso)
   8.217 +  {    
   8.218 +    flags |= NETTXF_csum_blank | NETTXF_data_validated; /* these may be implied but not specified when lso is used*/
   8.219 +    if (pi.tcp_length >= mss)
   8.220 +    {
   8.221 +      flags |= NETTXF_extra_info;
   8.222 +      xen_gso = TRUE;
   8.223 +    }
   8.224 +    else
   8.225 +    {
   8.226 +      KdPrint((__DRIVER_NAME "     large send specified when tcp_length < mss\n"));
   8.227 +    }
   8.228 +  }
   8.229 +
   8.230 +/*
   8.231 +* See io/netif.h. Must put (A) 1st request, then (B) optional extra_info, then
   8.232 +* (C) rest of requests on the ring. Only (A) has csum flags.
   8.233 +*/
   8.234 +
   8.235 +  /* (A) */
   8.236 +  tx0 = XenNet_PutCbOnRing(xi, coalesce_buf, pi.header_length, gref);
   8.237 +  ASSERT(tx0); /* this will never happen */
   8.238 +  tx0->flags = flags;
   8.239 +  tx_length += pi.header_length;
   8.240 +
   8.241 +  /* even though we haven't reported that we are capable of it, LSO demands that we calculate the IP Header checksum */
   8.242 +  if (ndis_lso)
   8.243 +  {
   8.244 +    XenNet_SumIpHeader(coalesce_buf, pi.ip4_header_length);
   8.245 +  }
   8.246 +  txN = tx0;
   8.247 +
   8.248 +  /* (B) */
   8.249 +  if (xen_gso)
   8.250 +  {
   8.251 +    ASSERT(flags & NETTXF_extra_info);
   8.252 +    ei = (struct netif_extra_info *)RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   8.253 +    //KdPrint((__DRIVER_NAME "     pos = %d\n", xi->tx.req_prod_pvt));
   8.254 +    xi->tx.req_prod_pvt++;
   8.255 +    xi->tx_ring_free--;
   8.256 +    ei->type = XEN_NETIF_EXTRA_TYPE_GSO;
   8.257 +    ei->flags = 0;
   8.258 +    ei->u.gso.size = (USHORT)mss;
   8.259 +    ei->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
   8.260 +    ei->u.gso.pad = 0;
   8.261 +    ei->u.gso.features = 0;
   8.262 +  }
   8.263 +
   8.264 +  ASSERT(xi->config_sg || !remaining);
   8.265 +  
   8.266 +  /* (C) - only if data is remaining */
   8.267 +  coalesce_buf = NULL;
   8.268 +  while (remaining > 0)
   8.269 +  {
   8.270 +    ULONG length;
   8.271 +    PFN_NUMBER pfn;
   8.272 +    
   8.273 +    ASSERT(pi.curr_buffer);
   8.274 +    if (coalesce_required)
   8.275 +    {
   8.276 +      PVOID va;
   8.277 +      if (!coalesce_buf)
   8.278 +      {
   8.279 +        gref = xi->vectors.GntTbl_GetRef(xi->vectors.context, (ULONG)'XNTX');
   8.280 +        if (gref == INVALID_GRANT_REF)
   8.281 +        {
   8.282 +          KdPrint((__DRIVER_NAME "     out of grefs - partial send\n"));
   8.283 +          break;
   8.284 +        }
   8.285 +        coalesce_buf = NdisAllocateFromNPagedLookasideList(&xi->tx_lookaside_list);
   8.286 +        if (!coalesce_buf)
   8.287 +        {
   8.288 +          xi->vectors.GntTbl_PutRef(xi->vectors.context, gref, (ULONG)'XNTX');
   8.289 +          KdPrint((__DRIVER_NAME "     out of memory - partial send\n"));
   8.290 +          break;
   8.291 +        }
   8.292 +        coalesce_remaining = min(PAGE_SIZE, remaining);
   8.293 +      }
   8.294 +      length = XenNet_QueryData(&pi, coalesce_remaining);
   8.295 +      va = NdisBufferVirtualAddressSafe(pi.curr_buffer, LowPagePriority);
   8.296 +      if (!va)
   8.297 +      {
   8.298 +        KdPrint((__DRIVER_NAME "     failed to map buffer va - partial send\n"));
   8.299 +        coalesce_remaining = 0;
   8.300 +        remaining -= min(PAGE_SIZE, remaining);
   8.301 +        NdisFreeToNPagedLookasideList(&xi->tx_lookaside_list, coalesce_buf);
   8.302 +      }
   8.303 +      else
   8.304 +      {
   8.305 +        memcpy((PUCHAR)coalesce_buf + min(PAGE_SIZE, remaining) - coalesce_remaining, (PUCHAR)va + pi.curr_mdl_offset, length);
   8.306 +        coalesce_remaining -= length;
   8.307 +      }
   8.308 +    }
   8.309 +    else
   8.310 +    {
   8.311 +      length = XenNet_QueryData(&pi, PAGE_SIZE);
   8.312 +    }
   8.313 +    if (!length || coalesce_remaining) /* sometimes there are zero length buffers... */
   8.314 +    {
   8.315 +      XenNet_EatData(&pi, length); /* do this so we actually move to the next buffer */
   8.316 +      continue;
   8.317 +    }
   8.318 +
   8.319 +    if (coalesce_buf)
   8.320 +    {
   8.321 +      if (remaining)
   8.322 +      {
   8.323 +        txN = XenNet_PutCbOnRing(xi, coalesce_buf, min(PAGE_SIZE, remaining), gref);
   8.324 +        ASSERT(txN);
   8.325 +        coalesce_buf = NULL;
   8.326 +        remaining -= min(PAGE_SIZE, remaining);
   8.327 +        tx_length += min(PAGE_SIZE, remaining);
   8.328 +      }
   8.329 +    }
   8.330 +    else
   8.331 +    {
   8.332 +      ULONG offset;
   8.333 +      
   8.334 +      gref = xi->vectors.GntTbl_GetRef(xi->vectors.context, (ULONG)'XNTX');
   8.335 +      if (gref == INVALID_GRANT_REF)
   8.336 +      {
   8.337 +        KdPrint((__DRIVER_NAME "     out of grefs - partial send\n"));
   8.338 +        break;
   8.339 +      }
   8.340 +      txN = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   8.341 +      xi->tx.req_prod_pvt++;
   8.342 +      xi->tx_ring_free--;
   8.343 +      txN->id = get_id_from_freelist(xi);
   8.344 +      ASSERT(!xi->tx_shadows[txN->id].cb);
   8.345 +      offset = MmGetMdlByteOffset(pi.curr_buffer) + pi.curr_mdl_offset;
   8.346 +      pfn = MmGetMdlPfnArray(pi.curr_buffer)[offset >> PAGE_SHIFT];
   8.347 +      txN->offset = (USHORT)offset & (PAGE_SIZE - 1);
   8.348 +      txN->gref = xi->vectors.GntTbl_GrantAccess(xi->vectors.context, 0, (ULONG)pfn, FALSE, gref, (ULONG)'XNTX');
   8.349 +      ASSERT(xi->tx_shadows[txN->id].gref == INVALID_GRANT_REF);
   8.350 +      xi->tx_shadows[txN->id].gref = txN->gref;
   8.351 +      //ASSERT(sg->Elements[sg_element].Length > sg_offset);
   8.352 +      txN->size = (USHORT)length;
   8.353 +      ASSERT(txN->offset + txN->size <= PAGE_SIZE);
   8.354 +      ASSERT(txN->size);
   8.355 +      ASSERT(txN->gref != INVALID_GRANT_REF);
   8.356 +      remaining -= length;
   8.357 +      tx_length += length;
   8.358 +    }
   8.359 +    tx0->size = tx0->size + txN->size;
   8.360 +    txN->flags = NETTXF_more_data;
   8.361 +    XenNet_EatData(&pi, length);
   8.362 +  }
   8.363 +  txN->flags &= ~NETTXF_more_data;
   8.364 +  ASSERT(tx0->size == pi.total_length);
   8.365 +  ASSERT(!xi->tx_shadows[txN->id].packet);
   8.366 +  xi->tx_shadows[txN->id].packet = packet;
   8.367 +
   8.368 +  if (ndis_lso)
   8.369 +  {
   8.370 +    //KdPrint((__DRIVER_NAME "     TcpLargeSendPacketInfo = %d\n", pi.tcp_length));
   8.371 +    NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo) = UlongToPtr(tx_length - MAX_ETH_HEADER_LENGTH - pi.ip4_header_length - pi.tcp_header_length);
   8.372 +  }
   8.373 +
   8.374 +  xi->stat_tx_ok++;
   8.375 +
   8.376 +  //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
   8.377 +  //FUNCTION_EXIT();
   8.378 +  xi->tx_outstanding++;
   8.379 +  return TRUE;
   8.380 +}
   8.381 +
   8.382 +/* Called at DISPATCH_LEVEL with tx_lock held */
   8.383 +
   8.384 +static VOID
   8.385 +XenNet_SendQueuedPackets(struct xennet_info *xi)
   8.386 +{
   8.387 +  PLIST_ENTRY entry;
   8.388 +  PNDIS_PACKET packet;
   8.389 +  int notify;
   8.390 +
   8.391 +  //FUNCTION_ENTER();
   8.392 +
   8.393 +  if (xi->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
   8.394 +    return;
   8.395 +
   8.396 +  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   8.397 +  /* if empty, the above returns head*, not NULL */
   8.398 +  while (entry != &xi->tx_waiting_pkt_list)
   8.399 +  {
   8.400 +    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   8.401 +    if (!XenNet_HWSendPacket(xi, packet))
   8.402 +    {
   8.403 +      //KdPrint((__DRIVER_NAME "     No room for packet\n"));
   8.404 +      InsertHeadList(&xi->tx_waiting_pkt_list, entry);
   8.405 +      break;
   8.406 +    }
   8.407 +    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   8.408 +  }
   8.409 +
   8.410 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->tx, notify);
   8.411 +  if (notify)
   8.412 +  {
   8.413 +    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->event_channel);
   8.414 +  }
   8.415 +  //FUNCTION_EXIT();
   8.416 +}
   8.417 +
   8.418 +//ULONG packets_outstanding = 0;
   8.419 +// Called at DISPATCH_LEVEL
   8.420 +VOID
   8.421 +XenNet_TxBufferGC(struct xennet_info *xi, BOOLEAN dont_set_event)
   8.422 +{
   8.423 +  RING_IDX cons, prod;
   8.424 +  PNDIS_PACKET head = NULL, tail = NULL;
   8.425 +  PNDIS_PACKET packet;
   8.426 +  ULONG tx_packets = 0;
   8.427 +
   8.428 +  //FUNCTION_ENTER();
   8.429 +
   8.430 +  if (!xi->connected)
   8.431 +    return; /* a delayed DPC could let this come through... just do nothing */
   8.432 +  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
   8.433 +
   8.434 +  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
   8.435 +
   8.436 +  if (xi->tx_shutting_down && !xi->tx_outstanding)
   8.437 +  {
   8.438 +    /* there is a chance that our Dpc had been queued just before the shutdown... */
   8.439 +    KeSetEvent(&xi->tx_idle_event, IO_NO_INCREMENT, FALSE);
   8.440 +    KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   8.441 +    return;
   8.442 +  }
   8.443 +
   8.444 +  do {
   8.445 +    prod = xi->tx.sring->rsp_prod;
   8.446 +    KeMemoryBarrier(); /* Ensure we see responses up to 'rsp_prod'. */
   8.447 +
   8.448 +    for (cons = xi->tx.rsp_cons; cons != prod; cons++)
   8.449 +    {
   8.450 +      struct netif_tx_response *txrsp;
   8.451 +      tx_shadow_t *shadow;
   8.452 +      
   8.453 +      txrsp = RING_GET_RESPONSE(&xi->tx, cons);
   8.454 +      
   8.455 +      xi->tx_ring_free++;
   8.456 +      
   8.457 +      if (txrsp->status == NETIF_RSP_NULL)
   8.458 +      {
   8.459 +        continue;
   8.460 +      }
   8.461 +
   8.462 +      shadow = &xi->tx_shadows[txrsp->id];
   8.463 +      if (shadow->cb)
   8.464 +      {
   8.465 +        NdisFreeToNPagedLookasideList(&xi->tx_lookaside_list, shadow->cb);
   8.466 +        shadow->cb = NULL;
   8.467 +      }
   8.468 +      
   8.469 +      if (shadow->gref != INVALID_GRANT_REF)
   8.470 +      {
   8.471 +        xi->vectors.GntTbl_EndAccess(xi->vectors.context,
   8.472 +          shadow->gref, FALSE, (ULONG)'XNTX');
   8.473 +        shadow->gref = INVALID_GRANT_REF;
   8.474 +      }
   8.475 +      
   8.476 +      if (shadow->packet)
   8.477 +      {
   8.478 +        packet = shadow->packet;
   8.479 +        *(PNDIS_PACKET *)&packet->MiniportReservedEx[0] = NULL;
   8.480 +        if (head)
   8.481 +          *(PNDIS_PACKET *)&tail->MiniportReservedEx[0] = packet;
   8.482 +        else
   8.483 +          head = packet;
   8.484 +        tail = packet;
   8.485 +        shadow->packet = NULL;
   8.486 +      }
   8.487 +      put_id_on_freelist(xi, txrsp->id);
   8.488 +    }
   8.489 +
   8.490 +    xi->tx.rsp_cons = prod;
   8.491 +    /* resist the temptation to set the event more than +1... it breaks things */
   8.492 +    if (!dont_set_event)
   8.493 +      xi->tx.sring->rsp_event = prod + 1;
   8.494 +    KeMemoryBarrier();
   8.495 +  } while (prod != xi->tx.sring->rsp_prod);
   8.496 +
   8.497 +  /* if queued packets, send them now */
   8.498 +  if (!xi->tx_shutting_down)
   8.499 +    XenNet_SendQueuedPackets(xi);
   8.500 +
   8.501 +  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   8.502 +
   8.503 +  /* must be done without holding any locks */
   8.504 +  while (head)
   8.505 +  {
   8.506 +    packet = (PNDIS_PACKET)head;
   8.507 +    head = *(PNDIS_PACKET *)&packet->MiniportReservedEx[0];
   8.508 +    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_SUCCESS);
   8.509 +    tx_packets++;
   8.510 +  }
   8.511 +
   8.512 +  /* must be done after we have truly given back all packets */
   8.513 +  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
   8.514 +  xi->tx_outstanding -= tx_packets;
   8.515 +  if (!xi->tx_outstanding && xi->tx_shutting_down)
   8.516 +    KeSetEvent(&xi->tx_idle_event, IO_NO_INCREMENT, FALSE);
   8.517 +  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   8.518 +
   8.519 +  if (xi->device_state->suspend_resume_state_pdo == SR_STATE_SUSPENDING
   8.520 +    && xi->device_state->suspend_resume_state_fdo != SR_STATE_SUSPENDING
   8.521 +    && xi->tx_id_free == NET_TX_RING_SIZE)
   8.522 +  {
   8.523 +    KdPrint((__DRIVER_NAME "     Setting SR_STATE_SUSPENDING\n"));
   8.524 +    xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING;
   8.525 +    KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
   8.526 +    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
   8.527 +  }
   8.528 +
   8.529 +  //FUNCTION_EXIT();
   8.530 +}
   8.531 +
   8.532 +// called at <= DISPATCH_LEVEL
   8.533 +VOID
   8.534 +XenNet_SendPackets(
   8.535 +  IN NDIS_HANDLE MiniportAdapterContext,
   8.536 +  IN PPNDIS_PACKET PacketArray,
   8.537 +  IN UINT NumberOfPackets
   8.538 +  )
   8.539 +{
   8.540 +  struct xennet_info *xi = MiniportAdapterContext;
   8.541 +  PNDIS_PACKET packet;
   8.542 +  UINT i;
   8.543 +  PLIST_ENTRY entry;
   8.544 +  KIRQL OldIrql;
   8.545 +
   8.546 +  //FUNCTION_ENTER();
   8.547 +
   8.548 +  if (xi->inactive)
   8.549 +  {
   8.550 +    for (i = 0; i < NumberOfPackets; i++)
   8.551 +    {
   8.552 +      NdisMSendComplete(xi->adapter_handle, PacketArray[i], NDIS_STATUS_FAILURE);
   8.553 +    }
   8.554 +    return;
   8.555 +  }
   8.556 +    
   8.557 +  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
   8.558 +
   8.559 +  for (i = 0; i < NumberOfPackets; i++)
   8.560 +  {
   8.561 +    packet = PacketArray[i];
   8.562 +    ASSERT(packet);
   8.563 +    *(ULONG *)&packet->MiniportReservedEx = 0;
   8.564 +    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   8.565 +    InsertTailList(&xi->tx_waiting_pkt_list, entry);
   8.566 +  }
   8.567 +
   8.568 +  XenNet_SendQueuedPackets(xi);
   8.569 +
   8.570 +  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
   8.571 +  
   8.572 +  //FUNCTION_EXIT();
   8.573 +}
   8.574 +
   8.575 +VOID
   8.576 +XenNet_CancelSendPackets(
   8.577 +  NDIS_HANDLE MiniportAdapterContext,
   8.578 +  PVOID CancelId)
   8.579 +{
   8.580 +  struct xennet_info *xi = MiniportAdapterContext;
   8.581 +  KIRQL old_irql;
   8.582 +  PLIST_ENTRY entry;
   8.583 +  PNDIS_PACKET packet;
   8.584 +  PNDIS_PACKET head = NULL, tail = NULL;
   8.585 +  BOOLEAN result;
   8.586 +
   8.587 +  FUNCTION_ENTER();
   8.588 +
   8.589 +  KeAcquireSpinLock(&xi->tx_lock, &old_irql);
   8.590 +
   8.591 +  entry = xi->tx_waiting_pkt_list.Flink;
   8.592 +  while (entry != &xi->tx_waiting_pkt_list)
   8.593 +  {
   8.594 +    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   8.595 +    entry = entry->Flink;
   8.596 +    if (NDIS_GET_PACKET_CANCEL_ID(packet) == CancelId)
   8.597 +    {
   8.598 +      KdPrint((__DRIVER_NAME "     Found packet to cancel %p\n", packet));
   8.599 +      result = RemoveEntryList((PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)]);
   8.600 +      ASSERT(result);
   8.601 +      *(PNDIS_PACKET *)&packet->MiniportReservedEx[0] = NULL;
   8.602 +      if (head)
   8.603 +        *(PNDIS_PACKET *)&tail->MiniportReservedEx[0] = packet;
   8.604 +      else
   8.605 +        head = packet;
   8.606 +      tail = packet;
   8.607 +    }
   8.608 +  }
   8.609 +
   8.610 +  KeReleaseSpinLock(&xi->tx_lock, old_irql);
   8.611 +
   8.612 +  while (head)
   8.613 +  {
   8.614 +    packet = (PNDIS_PACKET)head;
   8.615 +    head = *(PNDIS_PACKET *)&packet->MiniportReservedEx[0];
   8.616 +    KdPrint((__DRIVER_NAME "     NdisMSendComplete(%p)\n", packet));
   8.617 +    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_REQUEST_ABORTED);
   8.618 +  }
   8.619 +  
   8.620 +  FUNCTION_EXIT();
   8.621 +}
   8.622 +
   8.623 +VOID
   8.624 +XenNet_TxResumeStart(xennet_info_t *xi)
   8.625 +{
   8.626 +  UNREFERENCED_PARAMETER(xi);
   8.627 +
   8.628 +  FUNCTION_ENTER();
   8.629 +    /* nothing to do here - all packets were already sent */
   8.630 +  FUNCTION_EXIT();
   8.631 +}
   8.632 +
   8.633 +VOID
   8.634 +XenNet_TxResumeEnd(xennet_info_t *xi)
   8.635 +{
   8.636 +  KIRQL old_irql;
   8.637 +
   8.638 +  FUNCTION_ENTER();
   8.639 +
   8.640 +  KeAcquireSpinLock(&xi->tx_lock, &old_irql);
   8.641 +  XenNet_SendQueuedPackets(xi);
   8.642 +  KeReleaseSpinLock(&xi->tx_lock, old_irql);
   8.643 +
   8.644 +  FUNCTION_EXIT();
   8.645 +}
   8.646 +
   8.647 +BOOLEAN
   8.648 +XenNet_TxInit(xennet_info_t *xi)
   8.649 +{
   8.650 +  USHORT i;
   8.651 +
   8.652 +  KeInitializeSpinLock(&xi->tx_lock);
   8.653 +  InitializeListHead(&xi->tx_waiting_pkt_list);
   8.654 +
   8.655 +  KeInitializeEvent(&xi->tx_idle_event, SynchronizationEvent, FALSE);
   8.656 +  xi->tx_shutting_down = FALSE;
   8.657 +  xi->tx_outstanding = 0;
   8.658 +  xi->tx_ring_free = NET_TX_RING_SIZE;
   8.659 +  
   8.660 +  NdisInitializeNPagedLookasideList(&xi->tx_lookaside_list, NULL, NULL, 0,
   8.661 +    PAGE_SIZE, XENNET_POOL_TAG, 0);
   8.662 +
   8.663 +  xi->tx_id_free = 0;
   8.664 +  for (i = 0; i < NET_TX_RING_SIZE; i++)
   8.665 +  {
   8.666 +    xi->tx_shadows[i].gref = INVALID_GRANT_REF;
   8.667 +    xi->tx_shadows[i].cb = NULL;
   8.668 +    put_id_on_freelist(xi, i);
   8.669 +  }
   8.670 +
   8.671 +  return TRUE;
   8.672 +}
   8.673 +
   8.674 +/*
   8.675 +The ring is completely closed down now. We just need to empty anything left
   8.676 +on our freelists and harvest anything left on the rings.
   8.677 +*/
   8.678 +
   8.679 +BOOLEAN
   8.680 +XenNet_TxShutdown(xennet_info_t *xi)
   8.681 +{
   8.682 +  PLIST_ENTRY entry;
   8.683 +  PNDIS_PACKET packet;
   8.684 +  //PMDL mdl;
   8.685 +  //ULONG i;
   8.686 +  KIRQL OldIrql;
   8.687 +
   8.688 +  FUNCTION_ENTER();
   8.689 +
   8.690 +  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
   8.691 +  xi->tx_shutting_down = TRUE;
   8.692 +  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
   8.693 +
   8.694 +  while (xi->tx_outstanding)
   8.695 +  {
   8.696 +    KdPrint((__DRIVER_NAME "     Waiting for %d remaining packets to be sent\n", xi->tx_outstanding));
   8.697 +    KeWaitForSingleObject(&xi->tx_idle_event, Executive, KernelMode, FALSE, NULL);
   8.698 +  }
   8.699 +
   8.700 +#if (NTDDI_VERSION >= NTDDI_WINXP)
   8.701 +  KeFlushQueuedDpcs();
   8.702 +#endif
   8.703 +
   8.704 +  /* Free packets in tx queue */
   8.705 +  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   8.706 +  while (entry != &xi->tx_waiting_pkt_list)
   8.707 +  {
   8.708 +    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   8.709 +    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   8.710 +    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   8.711 +  }
   8.712 +
   8.713 +  NdisDeleteNPagedLookasideList(&xi->tx_lookaside_list);
   8.714 +
   8.715 +  FUNCTION_EXIT();
   8.716 +
   8.717 +  return TRUE;
   8.718 +}
     9.1 --- a/xennet/xennet_common.c	Sat Apr 30 00:24:01 2011 +1000
     9.2 +++ b/xennet/xennet_common.c	Sat Apr 30 10:57:23 2011 +1000
     9.3 @@ -1,286 +1,5 @@
     9.4 -/*
     9.5 -PV Net Driver for Windows Xen HVM Domains
     9.6 -Copyright (C) 2007 James Harper
     9.7 -Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
     9.8 -
     9.9 -This program is free software; you can redistribute it and/or
    9.10 -modify it under the terms of the GNU General Public License
    9.11 -as published by the Free Software Foundation; either version 2
    9.12 -of the License, or (at your option) any later version.
    9.13 -
    9.14 -This program is distributed in the hope that it will be useful,
    9.15 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.17 -GNU General Public License for more details.
    9.18 -
    9.19 -You should have received a copy of the GNU General Public License
    9.20 -along with this program; if not, write to the Free Software
    9.21 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    9.22 -*/
    9.23 -
    9.24 -#include "xennet.h"
    9.25 -
    9.26 -/* Increase the header to a certain size */
    9.27 -BOOLEAN
    9.28 -XenNet_BuildHeader(packet_info_t *pi, PUCHAR header, ULONG new_header_size)
    9.29 -{
    9.30 -  ULONG bytes_remaining;
    9.31 -
    9.32 -  //FUNCTION_ENTER();
    9.33 -
    9.34 -  if (!header)
    9.35 -    header = pi->header;
    9.36 -
    9.37 -  if (new_header_size <= pi->header_length)
    9.38 -  {
    9.39 -    return TRUE; /* header is already at least the required size */
    9.40 -  }
    9.41 -
    9.42 -  if (header == pi->first_buffer_virtual)
    9.43 -  {
    9.44 -    /* still working in the first buffer */
    9.45 -    if (new_header_size <= pi->first_buffer_length)
    9.46 -    {
    9.47 -      //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " new_header_size <= pi->first_buffer_length\n"));
    9.48 -      pi->header_length = new_header_size;
    9.49 -      if (pi->header_length == pi->first_buffer_length)
    9.50 -      {
    9.51 -        NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
    9.52 -        pi->curr_mdl_offset = 0;
    9.53 -        if (pi->curr_pb)
    9.54 -          pi->curr_pb = pi->curr_pb->next;
    9.55 -      }
    9.56 -      else
    9.57 -      {
    9.58 -        pi->curr_mdl_offset = (USHORT)new_header_size;
    9.59 -      }      
    9.60 -      return TRUE;
    9.61 -    }
    9.62 -    else
    9.63 -    {
    9.64 -      //KdPrint((__DRIVER_NAME "     Switching to header_data\n"));
    9.65 -      memcpy(pi->header_data, header, pi->header_length);
    9.66 -      header = pi->header = pi->header_data;
    9.67 -    }
    9.68 -  }
    9.69 -  
    9.70 -  bytes_remaining = new_header_size - pi->header_length;
    9.71 -  // TODO: if there are only a small number of bytes left in the current buffer then increase to consume that too... it would have to be no more than the size of header+mss though
    9.72 -
    9.73 -  //KdPrint((__DRIVER_NAME "     A bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
    9.74 -  while (bytes_remaining && pi->curr_buffer)
    9.75 -  {
    9.76 -    ULONG copy_size;
    9.77 -    
    9.78 -    ASSERT(pi->curr_buffer);
    9.79 -    //KdPrint((__DRIVER_NAME "     B bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
    9.80 -    if (MmGetMdlByteCount(pi->curr_buffer))
    9.81 -    {
    9.82 -      PUCHAR src_addr;
    9.83 -      src_addr = MmGetSystemAddressForMdlSafe(pi->curr_buffer, NormalPagePriority);
    9.84 -      if (!src_addr)
    9.85 -        return FALSE;
    9.86 -      copy_size = min(bytes_remaining, MmGetMdlByteCount(pi->curr_buffer) - pi->curr_mdl_offset);
    9.87 -      //KdPrint((__DRIVER_NAME "     B copy_size = %d\n", copy_size));
    9.88 -      memcpy(header + pi->header_length,
    9.89 -        src_addr + pi->curr_mdl_offset, copy_size);
    9.90 -      pi->curr_mdl_offset = (USHORT)(pi->curr_mdl_offset + copy_size);
    9.91 -      pi->header_length += copy_size;
    9.92 -      bytes_remaining -= copy_size;
    9.93 -    }
    9.94 -    if (pi->curr_mdl_offset == MmGetMdlByteCount(pi->curr_buffer))
    9.95 -    {
    9.96 -      NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
    9.97 -      if (pi->curr_pb)
    9.98 -        pi->curr_pb = pi->curr_pb->next;
    9.99 -      pi->curr_mdl_offset = 0;
   9.100 -    }
   9.101 -  }
   9.102 -  //KdPrint((__DRIVER_NAME "     C bytes_remaining = %d, pi->curr_buffer = %p, pi->mdl_count = %d\n", bytes_remaining, pi->curr_buffer, pi->mdl_count));
   9.103 -  if (bytes_remaining)
   9.104 -  {
   9.105 -    //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " bytes_remaining\n"));
   9.106 -    return FALSE;
   9.107 -  }
   9.108 -  //FUNCTION_EXIT();
   9.109 -  return TRUE;
   9.110 -}
   9.111 -
   9.112 -ULONG
   9.113 -XenNet_ParsePacketHeader(packet_info_t *pi, PUCHAR alt_buffer, ULONG min_header_size)
   9.114 -{
   9.115 -  //FUNCTION_ENTER();
   9.116 -
   9.117 -  ASSERT(pi->first_buffer);
   9.118 -  
   9.119 -  NdisQueryBufferSafe(pi->first_buffer, (PVOID)&pi->first_buffer_virtual, &pi->first_buffer_length, NormalPagePriority);
   9.120 -  pi->curr_buffer = pi->first_buffer;
   9.121 -  if (alt_buffer)
   9.122 -    pi->header = alt_buffer;
   9.123 -  else
   9.124 -    pi->header = pi->first_buffer_virtual;
   9.125 -
   9.126 -  pi->header_length = 0;
   9.127 -  pi->curr_mdl_offset = 0;
   9.128 -
   9.129 -  XenNet_BuildHeader(pi, NULL, min_header_size);
   9.130 -  
   9.131 -  if (!XenNet_BuildHeader(pi, NULL, (ULONG)XN_HDR_SIZE))
   9.132 -  {
   9.133 -    KdPrint((__DRIVER_NAME "     packet too small (Ethernet Header)\n"));
   9.134 -    return PARSE_TOO_SMALL;
   9.135 -  }
   9.136 -
   9.137 -  switch (GET_NET_PUSHORT(&pi->header[12])) // L2 protocol field
   9.138 -  {
   9.139 -  case 0x0800:
   9.140 -    //KdPrint((__DRIVER_NAME "     IP\n"));
   9.141 -    if (pi->header_length < (ULONG)(XN_HDR_SIZE + 20))
   9.142 -    {
   9.143 -      if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + 20)))
   9.144 -      {
   9.145 -        KdPrint((__DRIVER_NAME "     packet too small (IP Header)\n"));
   9.146 -        return PARSE_TOO_SMALL;
   9.147 -      }
   9.148 -    }
   9.149 -    pi->ip_version = (pi->header[XN_HDR_SIZE + 0] & 0xF0) >> 4;
   9.150 -    if (pi->ip_version != 4)
   9.151 -    {
   9.152 -      KdPrint((__DRIVER_NAME "     ip_version = %d\n", pi->ip_version));
   9.153 -      return PARSE_UNKNOWN_TYPE;
   9.154 -    }
   9.155 -    pi->ip4_header_length = (pi->header[XN_HDR_SIZE + 0] & 0x0F) << 2;
   9.156 -    if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20))
   9.157 -    {
   9.158 -      if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)))
   9.159 -      {
   9.160 -        //KdPrint((__DRIVER_NAME "     packet too small (IP Header + IP Options + TCP Header)\n"));
   9.161 -        return PARSE_TOO_SMALL;
   9.162 -      }
   9.163 -    }
   9.164 -    break;
   9.165 -  default:
   9.166 -    //KdPrint((__DRIVER_NAME "     Not IP (%d)\n", GET_NET_PUSHORT(&pi->header[12])));
   9.167 -    return PARSE_UNKNOWN_TYPE;
   9.168 -  }
   9.169 -  pi->ip_proto = pi->header[XN_HDR_SIZE + 9];
   9.170 -  switch (pi->ip_proto)
   9.171 -  {
   9.172 -  case 6:  // TCP
   9.173 -  case 17: // UDP
   9.174 -    break;
   9.175 -  default:
   9.176 -    //KdPrint((__DRIVER_NAME "     Not TCP/UDP (%d)\n", pi->ip_proto));
   9.177 -    return PARSE_UNKNOWN_TYPE;
   9.178 -  }
   9.179 -  pi->ip4_length = GET_NET_PUSHORT(&pi->header[XN_HDR_SIZE + 2]);
   9.180 -  pi->tcp_header_length = (pi->header[XN_HDR_SIZE + pi->ip4_header_length + 12] & 0xf0) >> 2;
   9.181 -
   9.182 -  if (pi->header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length))
   9.183 -  {
   9.184 -    if (!XenNet_BuildHeader(pi, NULL, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length)))
   9.185 -    {
   9.186 -      //KdPrint((__DRIVER_NAME "     packet too small (IP Header + IP Options + TCP Header + TCP Options)\n"));
   9.187 -      return PARSE_TOO_SMALL;
   9.188 -    }
   9.189 -  }
   9.190 -  
   9.191 -  if ((ULONG)XN_HDR_SIZE + pi->ip4_length > pi->total_length)
   9.192 -  {
   9.193 -    KdPrint((__DRIVER_NAME "     XN_HDR_SIZE + ip4_length (%d) > total_length (%d)\n", XN_HDR_SIZE + pi->ip4_length, pi->total_length));
   9.194 -    return PARSE_UNKNOWN_TYPE;
   9.195 -  }
   9.196 -
   9.197 -  pi->tcp_length = pi->ip4_length - pi->ip4_header_length - pi->tcp_header_length;
   9.198 -  pi->tcp_remaining = pi->tcp_length;
   9.199 -  pi->tcp_seq = GET_NET_PULONG(&pi->header[XN_HDR_SIZE + pi->ip4_header_length + 4]);
   9.200 -  pi->tcp_has_options = (BOOLEAN)(pi->tcp_header_length > 20);
   9.201 -  if (pi->mss > 0 && pi->tcp_length > pi->mss)
   9.202 -    pi->split_required = TRUE;
   9.203 -
   9.204 -  //KdPrint((__DRIVER_NAME "     ip4_length = %d\n", pi->ip4_length));
   9.205 -  //KdPrint((__DRIVER_NAME "     tcp_length = %d\n", pi->tcp_length));
   9.206 -  //FUNCTION_EXIT();
   9.207 -  
   9.208 -  return PARSE_OK;
   9.209 -}
   9.210 -
   9.211 -VOID
   9.212 -XenNet_SumIpHeader(
   9.213 -  PUCHAR header,
   9.214 -  USHORT ip4_header_length
   9.215 -)
   9.216 -{
   9.217 -  ULONG csum = 0;
   9.218 -  USHORT i;
   9.219 -
   9.220 -  ASSERT(ip4_header_length > 12);
   9.221 -  ASSERT(!(ip4_header_length & 1));
   9.222 -
   9.223 -  header[XN_HDR_SIZE + 10] = 0;
   9.224 -  header[XN_HDR_SIZE + 11] = 0;
   9.225 -  for (i = 0; i < ip4_header_length; i += 2)
   9.226 -  {
   9.227 -    csum += GET_NET_PUSHORT(&header[XN_HDR_SIZE + i]);
   9.228 -  }
   9.229 -  while (csum & 0xFFFF0000)
   9.230 -    csum = (csum & 0xFFFF) + (csum >> 16);
   9.231 -  csum = ~csum;
   9.232 -  SET_NET_USHORT(&header[XN_HDR_SIZE + 10], (USHORT)csum);
   9.233 -}
   9.234 -
   9.235 -BOOLEAN
   9.236 -XenNet_FilterAcceptPacket(struct xennet_info *xi,packet_info_t *pi)
   9.237 -{
   9.238 -  BOOLEAN is_multicast = FALSE;
   9.239 -  BOOLEAN is_my_multicast = FALSE;
   9.240 -  BOOLEAN is_broadcast = FALSE;
   9.241 -  BOOLEAN is_directed = FALSE;
   9.242 -  ULONG i;
   9.243 -
   9.244 -  if (pi->header[0] == 0xFF && pi->header[1] == 0xFF
   9.245 -      && pi->header[2] == 0xFF && pi->header[3] == 0xFF
   9.246 -      && pi->header[4] == 0xFF && pi->header[5] == 0xFF)
   9.247 -  {
   9.248 -    is_broadcast = TRUE;
   9.249 -  }
   9.250 -  else if (pi->header[0] & 0x01)
   9.251 -  {
   9.252 -    is_multicast = TRUE;
   9.253 -    for (i = 0; i < xi->multicast_list_size; i++)
   9.254 -    {
   9.255 -      if (memcmp(xi->multicast_list[i], pi->header, 6) == 0)
   9.256 -        break;
   9.257 -    }
   9.258 -    if (i < xi->multicast_list_size)
   9.259 -    {
   9.260 -      is_my_multicast = TRUE;
   9.261 -    }    
   9.262 -  }
   9.263 -  if (memcmp(xi->curr_mac_addr, pi->header, ETH_ALEN) == 0)
   9.264 -  {
   9.265 -    is_directed = TRUE;
   9.266 -  }
   9.267 -
   9.268 -  if (is_directed && (xi->packet_filter & NDIS_PACKET_TYPE_DIRECTED))
   9.269 -  {
   9.270 -    return TRUE;
   9.271 -  }  
   9.272 -  if (is_my_multicast && (xi->packet_filter & NDIS_PACKET_TYPE_MULTICAST))
   9.273 -  {
   9.274 -    return TRUE;
   9.275 -  }
   9.276 -  if (is_multicast && (xi->packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST))
   9.277 -  {
   9.278 -    return TRUE;
   9.279 -  }
   9.280 -  if (is_broadcast && (xi->packet_filter & NDIS_PACKET_TYPE_BROADCAST))
   9.281 -  {
   9.282 -    return TRUE;
   9.283 -  }
   9.284 -  if (xi->packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS)
   9.285 -  {
   9.286 -    return TRUE;
   9.287 -  }
   9.288 -  return FALSE;
   9.289 -}
   9.290 +#ifdef _GPLPV_NDIS5
   9.291 +#include "xennet5_common.c"
   9.292 +#else
   9.293 +#include "xennet5_common.c"
   9.294 +#endif
    10.1 --- a/xennet/xennet_oid.c	Sat Apr 30 00:24:01 2011 +1000
    10.2 +++ b/xennet/xennet_oid.c	Sat Apr 30 10:57:23 2011 +1000
    10.3 @@ -1,772 +1,5 @@
    10.4 -/*
    10.5 -PV Net Driver for Windows Xen HVM Domains
    10.6 -Copyright (C) 2007 James Harper
    10.7 -Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
    10.8 -
    10.9 -This program is free software; you can redistribute it and/or
   10.10 -modify it under the terms of the GNU General Public License
   10.11 -as published by the Free Software Foundation; either version 2
   10.12 -of the License, or (at your option) any later version.
   10.13 -
   10.14 -This program is distributed in the hope that it will be useful,
   10.15 -but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.17 -GNU General Public License for more details.
   10.18 -
   10.19 -You should have received a copy of the GNU General Public License
   10.20 -along with this program; if not, write to the Free Software
   10.21 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   10.22 -*/
   10.23 -
   10.24 -#include "xennet.h"
   10.25 -
   10.26 -// Q = Query Mandatory, S = Set Mandatory
   10.27 -NDIS_OID supported_oids[] =
   10.28 -{
   10.29 -  /* general OIDs */
   10.30 -  OID_GEN_SUPPORTED_LIST,        // Q
   10.31 -  OID_GEN_HARDWARE_STATUS,       // Q
   10.32 -  OID_GEN_MEDIA_SUPPORTED,       // Q
   10.33 -  OID_GEN_MEDIA_IN_USE,          // Q
   10.34 -  OID_GEN_MAXIMUM_LOOKAHEAD,     // Q
   10.35 -  OID_GEN_MAXIMUM_FRAME_SIZE,    // Q
   10.36 -  OID_GEN_LINK_SPEED,            // Q
   10.37 -  OID_GEN_TRANSMIT_BUFFER_SPACE, // Q
   10.38 -  OID_GEN_RECEIVE_BUFFER_SPACE,  // Q
   10.39 -  OID_GEN_TRANSMIT_BLOCK_SIZE,   // Q
   10.40 -  OID_GEN_RECEIVE_BLOCK_SIZE,    // Q
   10.41 -  OID_GEN_VENDOR_ID,             // Q
   10.42 -  OID_GEN_VENDOR_DESCRIPTION,    // Q
   10.43 -  OID_GEN_CURRENT_PACKET_FILTER, // QS
   10.44 -  OID_GEN_CURRENT_LOOKAHEAD,     // QS
   10.45 -  OID_GEN_DRIVER_VERSION,        // Q
   10.46 -  OID_GEN_VENDOR_DRIVER_VERSION, // Q
   10.47 -  OID_GEN_MAXIMUM_TOTAL_SIZE,    // Q
   10.48 -  OID_GEN_PROTOCOL_OPTIONS,      // S
   10.49 -  OID_GEN_MAC_OPTIONS,           // Q
   10.50 -  OID_GEN_MEDIA_CONNECT_STATUS,  // Q
   10.51 -  OID_GEN_MAXIMUM_SEND_PACKETS,  // Q
   10.52 -  /* stats */
   10.53 -  OID_GEN_XMIT_OK,               // Q
   10.54 -  OID_GEN_RCV_OK,                // Q
   10.55 -  OID_GEN_XMIT_ERROR,            // Q
   10.56 -  OID_GEN_RCV_ERROR,             // Q
   10.57 -  OID_GEN_RCV_NO_BUFFER,         // Q
   10.58 -  /* media-specific OIDs */
   10.59 -  OID_802_3_PERMANENT_ADDRESS,
   10.60 -  OID_802_3_CURRENT_ADDRESS,
   10.61 -  OID_802_3_MULTICAST_LIST,
   10.62 -  OID_802_3_MAXIMUM_LIST_SIZE,
   10.63 -  OID_802_3_RCV_ERROR_ALIGNMENT,
   10.64 -  OID_802_3_XMIT_ONE_COLLISION,
   10.65 -  OID_802_3_XMIT_MORE_COLLISIONS,
   10.66 -  /* tcp offload */
   10.67 -  OID_TCP_TASK_OFFLOAD,
   10.68 -  /* power */
   10.69 -  OID_PNP_CAPABILITIES,
   10.70 -  OID_PNP_SET_POWER,
   10.71 -  OID_PNP_QUERY_POWER,
   10.72 -};
   10.73 -
   10.74 -/* return 4 or 8 depending on size of buffer */
   10.75 -#define HANDLE_STAT_RETURN \
   10.76 -  {if (InformationBufferLength == 4) { \
   10.77 -    len = 4; *BytesNeeded = 8; \
   10.78 -    } else { \
   10.79 -    len = 8; \
   10.80 -    } }
   10.81 -
   10.82 -NDIS_STATUS
   10.83 -XenNet_QueryInformation(
   10.84 -  IN NDIS_HANDLE MiniportAdapterContext,
   10.85 -  IN NDIS_OID Oid,
   10.86 -  IN PVOID InformationBuffer,
   10.87 -  IN ULONG InformationBufferLength,
   10.88 -  OUT PULONG BytesWritten,
   10.89 -  OUT PULONG BytesNeeded)
   10.90 -{
   10.91 -  struct xennet_info *xi = MiniportAdapterContext;
   10.92 -  UCHAR vendor_desc[] = XN_VENDOR_DESC;
   10.93 -  ULONG64 temp_data;
   10.94 -  PVOID data = &temp_data;
   10.95 -  UINT len = 4;
   10.96 -  BOOLEAN used_temp_buffer = TRUE;
   10.97 -  NDIS_STATUS status = NDIS_STATUS_SUCCESS;
   10.98 -  PNDIS_TASK_OFFLOAD_HEADER ntoh;
   10.99 -  PNDIS_TASK_OFFLOAD nto;
  10.100 -  PNDIS_TASK_TCP_IP_CHECKSUM nttic;
  10.101 -  PNDIS_TASK_TCP_LARGE_SEND nttls;
  10.102 -  PNDIS_PNP_CAPABILITIES npc;
  10.103 -
  10.104 -  *BytesNeeded = 0;
  10.105 -  *BytesWritten = 0;
  10.106 -
  10.107 -// FUNCTION_ENTER()
  10.108 -
  10.109 -  switch(Oid)
  10.110 -  {
  10.111 -    case OID_GEN_SUPPORTED_LIST:
  10.112 -      data = supported_oids;
  10.113 -      len = sizeof(supported_oids);
  10.114 -      break;
  10.115 -    case OID_GEN_HARDWARE_STATUS:
  10.116 -      if (!xi->connected)
  10.117 -      {
  10.118 -        temp_data = NdisHardwareStatusInitializing;
  10.119 -        FUNCTION_MSG("NdisHardwareStatusInitializing\n");
  10.120 -      }
  10.121 -      else
  10.122 -      {
  10.123 -        temp_data = NdisHardwareStatusReady;
  10.124 -        FUNCTION_MSG("NdisHardwareStatusReady\n");
  10.125 -      }
  10.126 -      break;
  10.127 -    case OID_GEN_MEDIA_SUPPORTED:
  10.128 -      temp_data = NdisMedium802_3;
  10.129 -      break;
  10.130 -    case OID_GEN_MEDIA_IN_USE:
  10.131 -      temp_data = NdisMedium802_3;
  10.132 -      break;
  10.133 -    case OID_GEN_MAXIMUM_LOOKAHEAD:
  10.134 -      temp_data = MAX_LOOKAHEAD_LENGTH; //xi->config_mtu;
  10.135 -      break;
  10.136 -    case OID_GEN_MAXIMUM_FRAME_SIZE:
  10.137 -      temp_data = xi->config_mtu;
  10.138 -      break;
  10.139 -    case OID_GEN_LINK_SPEED:
  10.140 -      temp_data = 10000000; /* 1Gb */
  10.141 -      break;
  10.142 -    case OID_GEN_TRANSMIT_BUFFER_SPACE:
  10.143 -      /* multiply this by some small number as we can queue additional packets */
  10.144 -      temp_data = PAGE_SIZE * NET_TX_RING_SIZE * 4;
  10.145 -      break;
  10.146 -    case OID_GEN_RECEIVE_BUFFER_SPACE:
  10.147 -      temp_data = PAGE_SIZE * NET_RX_RING_SIZE * 2;
  10.148 -      break;
  10.149 -    case OID_GEN_TRANSMIT_BLOCK_SIZE:
  10.150 -      temp_data = PAGE_SIZE; //XN_MAX_PKT_SIZE;
  10.151 -      break;
  10.152 -    case OID_GEN_RECEIVE_BLOCK_SIZE:
  10.153 -      temp_data = PAGE_SIZE; //XN_MAX_PKT_SIZE;
  10.154 -      break;
  10.155 -    case OID_GEN_VENDOR_ID:
  10.156 -      temp_data = 0xFFFFFF; // Not guaranteed to be XENSOURCE_MAC_HDR;
  10.157 -      break;
  10.158 -    case OID_GEN_VENDOR_DESCRIPTION:
  10.159 -      data = vendor_desc;
  10.160 -      len = sizeof(vendor_desc);
  10.161 -      break;
  10.162 -    case OID_GEN_CURRENT_PACKET_FILTER:
  10.163 -      temp_data = xi->packet_filter;
  10.164 -      break;
  10.165 -    case OID_GEN_CURRENT_LOOKAHEAD:
  10.166 -      temp_data = xi->current_lookahead;
  10.167 -      break;
  10.168 -    case OID_GEN_DRIVER_VERSION:
  10.169 -      temp_data = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
  10.170 -      len = 2;
  10.171 -      break;
  10.172 -    case OID_GEN_VENDOR_DRIVER_VERSION:
  10.173 -      temp_data = VENDOR_DRIVER_VERSION;
  10.174 -      len = 4;
  10.175 -      break;
  10.176 -    case OID_GEN_MAXIMUM_TOTAL_SIZE:
  10.177 -      temp_data = xi->config_mtu + XN_HDR_SIZE;
  10.178 -      break;
  10.179 -    case OID_GEN_MAC_OPTIONS:
  10.180 -      temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 
  10.181 -        NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
  10.182 -        NDIS_MAC_OPTION_NO_LOOPBACK;
  10.183 -      break;
  10.184 -    case OID_GEN_MEDIA_CONNECT_STATUS:
  10.185 -      if (xi->connected && !xi->inactive)
  10.186 -        temp_data = NdisMediaStateConnected;
  10.187 -      else
  10.188 -        temp_data = NdisMediaStateDisconnected;
  10.189 -      break;
  10.190 -    case OID_GEN_MAXIMUM_SEND_PACKETS:
  10.191 -      /* this is actually ignored for deserialised drivers like us */
  10.192 -      temp_data = 0; //XN_MAX_SEND_PKTS;
  10.193 -      break;
  10.194 -    case OID_GEN_XMIT_OK:
  10.195 -      temp_data = xi->stat_tx_ok;
  10.196 -      HANDLE_STAT_RETURN;
  10.197 -      break;
  10.198 -    case OID_GEN_RCV_OK:
  10.199 -      temp_data = xi->stat_rx_ok;
  10.200 -      HANDLE_STAT_RETURN;
  10.201 -      break;
  10.202 -    case OID_GEN_XMIT_ERROR:
  10.203 -      temp_data = xi->stat_tx_error;
  10.204 -      HANDLE_STAT_RETURN;
  10.205 -      break;
  10.206 -    case OID_GEN_RCV_ERROR:
  10.207 -      temp_data = xi->stat_rx_error;
  10.208 -      HANDLE_STAT_RETURN;
  10.209 -      break;
  10.210 -    case OID_GEN_RCV_NO_BUFFER:
  10.211 -      temp_data = xi->stat_rx_no_buffer;
  10.212 -      HANDLE_STAT_RETURN;
  10.213 -      break;
  10.214 -    case OID_802_3_PERMANENT_ADDRESS:
  10.215 -      data = xi->perm_mac_addr;
  10.216 -      len = ETH_ALEN;
  10.217 -      break;
  10.218 -    case OID_802_3_CURRENT_ADDRESS:
  10.219 -      data = xi->curr_mac_addr;
  10.220 -      len = ETH_ALEN;
  10.221 -      break;
  10.222 -    case OID_802_3_RCV_ERROR_ALIGNMENT:
  10.223 -    case OID_802_3_XMIT_ONE_COLLISION:
  10.224 -    case OID_802_3_XMIT_MORE_COLLISIONS:
  10.225 -      temp_data = 0;
  10.226 -      HANDLE_STAT_RETURN;
  10.227 -      break;
  10.228 -    case OID_802_3_MULTICAST_LIST:
  10.229 -      data = xi->multicast_list;
  10.230 -      len = xi->multicast_list_size * 6;
  10.231 -      break;
  10.232 -    case OID_802_3_MAXIMUM_LIST_SIZE:
  10.233 -      temp_data = MULTICAST_LIST_MAX_SIZE;
  10.234 -      break;
  10.235 -    case OID_TCP_TASK_OFFLOAD:
  10.236 -      KdPrint(("Get OID_TCP_TASK_OFFLOAD\n"));
  10.237 -      /* it's times like this that C really sucks */
  10.238 -
  10.239 -      len = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  10.240 -
  10.241 -      if (xi->config_csum)
  10.242 -      {
  10.243 -        len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
  10.244 -          + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  10.245 -      }
  10.246 -
  10.247 -      if (xi->config_gso)
  10.248 -      {
  10.249 -        len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
  10.250 -          + sizeof(NDIS_TASK_TCP_LARGE_SEND);
  10.251 -      }
  10.252 -
  10.253 -      //len += 1024;
  10.254 -
  10.255 -      if (len > InformationBufferLength)
  10.256 -      {
  10.257 -          break;
  10.258 -      }
  10.259 -
  10.260 -      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
  10.261 -      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
  10.262 -        || ntoh->Size != sizeof(*ntoh)
  10.263 -        || !(
  10.264 -          ntoh->EncapsulationFormat.Encapsulation == IEEE_802_3_Encapsulation
  10.265 -          || (ntoh->EncapsulationFormat.Encapsulation == UNSPECIFIED_Encapsulation
  10.266 -              && ntoh->EncapsulationFormat.EncapsulationHeaderSize == XN_HDR_SIZE)))
  10.267 -      {
  10.268 -        status = NDIS_STATUS_NOT_SUPPORTED;
  10.269 -        break;
  10.270 -      }
  10.271 -      ntoh->OffsetFirstTask = 0; 
  10.272 -      nto = NULL;
  10.273 -
  10.274 -      if (xi->config_csum)
  10.275 -      {
  10.276 -        if (ntoh->OffsetFirstTask == 0)
  10.277 -        {
  10.278 -          ntoh->OffsetFirstTask = ntoh->Size;
  10.279 -          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
  10.280 -        }
  10.281 -        else
  10.282 -        {
  10.283 -          nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
  10.284 -            + nto->TaskBufferLength;
  10.285 -          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
  10.286 -        }
  10.287 -        /* fill in first nto */
  10.288 -        nto->Version = NDIS_TASK_OFFLOAD_VERSION;
  10.289 -        nto->Size = sizeof(NDIS_TASK_OFFLOAD);
  10.290 -        nto->Task = TcpIpChecksumNdisTask;
  10.291 -        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  10.292 -
  10.293 -        KdPrint(("config_csum enabled\n"));
  10.294 -        KdPrint(("nto = %p\n", nto));
  10.295 -        KdPrint(("nto->Size = %d\n", nto->Size));
  10.296 -        KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
  10.297 -
  10.298 -        /* fill in checksum offload struct */
  10.299 -        nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
  10.300 -        nttic->V4Transmit.IpChecksum = 0;
  10.301 -        nttic->V4Transmit.IpOptionsSupported = 0;
  10.302 -        nttic->V4Transmit.TcpChecksum = 1;
  10.303 -        nttic->V4Transmit.TcpOptionsSupported = 1;
  10.304 -        nttic->V4Transmit.UdpChecksum = 1;
  10.305 -        nttic->V4Receive.IpChecksum = 1;
  10.306 -        nttic->V4Receive.IpOptionsSupported = 1;
  10.307 -        nttic->V4Receive.TcpChecksum = 1;
  10.308 -        nttic->V4Receive.TcpOptionsSupported = 1;
  10.309 -        nttic->V4Receive.UdpChecksum = 1;
  10.310 -        nttic->V6Transmit.IpOptionsSupported = 0;
  10.311 -        nttic->V6Transmit.TcpOptionsSupported = 0;
  10.312 -        nttic->V6Transmit.TcpChecksum = 0;
  10.313 -        nttic->V6Transmit.UdpChecksum = 0;
  10.314 -        nttic->V6Receive.IpOptionsSupported = 0;
  10.315 -        nttic->V6Receive.TcpOptionsSupported = 0;
  10.316 -        nttic->V6Receive.TcpChecksum = 0;
  10.317 -        nttic->V6Receive.UdpChecksum = 0;
  10.318 -      }
  10.319 -      if (xi->config_gso)
  10.320 -      {
  10.321 -        if (ntoh->OffsetFirstTask == 0)
  10.322 -        {
  10.323 -          ntoh->OffsetFirstTask = ntoh->Size;
  10.324 -          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
  10.325 -        }
  10.326 -        else
  10.327 -        {
  10.328 -          nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
  10.329 -            + nto->TaskBufferLength;
  10.330 -          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
  10.331 -        }
  10.332 -  
  10.333 -        /* fill in second nto */
  10.334 -        nto->Version = NDIS_TASK_OFFLOAD_VERSION;
  10.335 -        nto->Size = sizeof(NDIS_TASK_OFFLOAD);
  10.336 -        nto->Task = TcpLargeSendNdisTask;
  10.337 -        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
  10.338 -
  10.339 -        KdPrint(("config_gso enabled\n"));
  10.340 -        KdPrint(("nto = %p\n", nto));
  10.341 -        KdPrint(("nto->Size = %d\n", nto->Size));
  10.342 -        KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
  10.343 -  
  10.344 -        /* fill in large send struct */
  10.345 -        nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
  10.346 -        nttls->Version = 0;
  10.347 -        nttls->MaxOffLoadSize = xi->config_gso;
  10.348 -        nttls->MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
  10.349 -        nttls->TcpOptions = FALSE; /* linux can't handle this */
  10.350 -        nttls->IpOptions = FALSE; /* linux can't handle this */
  10.351 -        KdPrint(("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions)));        
  10.352 -      }
  10.353 -
  10.354 -      if (nto)
  10.355 -        nto->OffsetNextTask = 0; /* last one */
  10.356 -
  10.357 -      used_temp_buffer = FALSE;
  10.358 -      break;
  10.359 -    case OID_IP4_OFFLOAD_STATS:
  10.360 -    case OID_IP6_OFFLOAD_STATS:
  10.361 -      /* these are called often so just ignore then quietly */
  10.362 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.363 -      break;
  10.364 -
  10.365 -    case OID_PNP_CAPABILITIES:
  10.366 -      KdPrint(("Get OID_PNP_CAPABILITIES\n"));
  10.367 -      len = sizeof(NDIS_PNP_CAPABILITIES);
  10.368 -      if (len > InformationBufferLength)
  10.369 -        break;
  10.370 -      npc = (PNDIS_PNP_CAPABILITIES)InformationBuffer;
  10.371 -      npc->Flags = 0;
  10.372 -      npc->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
  10.373 -      npc->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
  10.374 -      npc->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
  10.375 -      used_temp_buffer = FALSE;
  10.376 -      break;
  10.377 -    case OID_PNP_QUERY_POWER:
  10.378 -      KdPrint(("Get OID_PNP_CAPABILITIES\n"));
  10.379 -      used_temp_buffer = FALSE;
  10.380 -      break;
  10.381 -
  10.382 -    default:
  10.383 -      KdPrint(("Get Unknown OID 0x%x\n", Oid));
  10.384 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.385 -  }
  10.386 -
  10.387 -  if (!NT_SUCCESS(status))
  10.388 -  {
  10.389 -    //FUNCTION_EXIT_STATUS(status);
  10.390 -    return status;
  10.391 -  }
  10.392 -
  10.393 -  if (len > InformationBufferLength)
  10.394 -  {
  10.395 -    *BytesNeeded = len;
  10.396 -    FUNCTION_MSG("(BUFFER_TOO_SHORT %d > %d)\n", len, InformationBufferLength);
  10.397 -    return NDIS_STATUS_BUFFER_TOO_SHORT;
  10.398 -  }
  10.399 -
  10.400 -  *BytesWritten = len;
  10.401 -  if (len && used_temp_buffer)
  10.402 -  {
  10.403 -    NdisMoveMemory((PUCHAR)InformationBuffer, data, len);
  10.404 -  }
  10.405 -
  10.406 -  //KdPrint(("Got OID 0x%x\n", Oid));
  10.407 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  10.408 -
  10.409 -  return status;
  10.410 -}
  10.411 -
  10.412 -NDIS_STATUS
  10.413 -XenNet_SetInformation(
  10.414 -  IN NDIS_HANDLE MiniportAdapterContext,
  10.415 -  IN NDIS_OID Oid,
  10.416 -  IN PVOID InformationBuffer,
  10.417 -  IN ULONG InformationBufferLength,
  10.418 -  OUT PULONG BytesRead,
  10.419 -  OUT PULONG BytesNeeded
  10.420 -  )
  10.421 -{
  10.422 -  NTSTATUS status;
  10.423 -  ULONG i;
  10.424 -  struct xennet_info *xi = MiniportAdapterContext;
  10.425 -  PULONG64 data = InformationBuffer;
  10.426 -  PNDIS_TASK_OFFLOAD_HEADER ntoh;
  10.427 -  PNDIS_TASK_OFFLOAD nto;
  10.428 -  PNDIS_TASK_TCP_IP_CHECKSUM nttic = NULL;
  10.429 -  PNDIS_TASK_TCP_LARGE_SEND nttls = NULL;
  10.430 -  UCHAR *multicast_list;
  10.431 -  int offset;
  10.432 -
  10.433 -  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
  10.434 -
  10.435 -  UNREFERENCED_PARAMETER(MiniportAdapterContext);
  10.436 -  UNREFERENCED_PARAMETER(InformationBufferLength);
  10.437 -  UNREFERENCED_PARAMETER(BytesRead);
  10.438 -  UNREFERENCED_PARAMETER(BytesNeeded);
  10.439 -
  10.440 -  switch(Oid)
  10.441 -  {
  10.442 -    case OID_GEN_SUPPORTED_LIST:
  10.443 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.444 -      KdPrint(("Unsupported set OID_GEN_SUPPORTED_LIST\n"));
  10.445 -      break;
  10.446 -    case OID_GEN_HARDWARE_STATUS:
  10.447 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.448 -      KdPrint(("Unsupported set OID_GEN_HARDWARE_STATUS\n"));
  10.449 -      break;
  10.450 -    case OID_GEN_MEDIA_SUPPORTED:
  10.451 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.452 -      KdPrint(("Unsupported set OID_GEN_MEDIA_SUPPORTED\n"));
  10.453 -      break;
  10.454 -    case OID_GEN_MEDIA_IN_USE:
  10.455 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.456 -      KdPrint(("Unsupported set OID_GEN_MEDIA_IN_USE\n"));
  10.457 -      break;
  10.458 -    case OID_GEN_MAXIMUM_LOOKAHEAD:
  10.459 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.460 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_LOOKAHEAD\n"));
  10.461 -      break;
  10.462 -    case OID_GEN_MAXIMUM_FRAME_SIZE:
  10.463 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.464 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_FRAME_SIZE\n"));
  10.465 -      break;
  10.466 -    case OID_GEN_LINK_SPEED:
  10.467 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.468 -      KdPrint(("Unsupported set OID_GEN_LINK_SPEED\n"));
  10.469 -      break;
  10.470 -    case OID_GEN_TRANSMIT_BUFFER_SPACE:
  10.471 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.472 -      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
  10.473 -      break;
  10.474 -    case OID_GEN_RECEIVE_BUFFER_SPACE:
  10.475 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.476 -      KdPrint(("Unsupported set OID_GEN_RECEIVE_BUFFER_SPACE\n"));
  10.477 -      break;
  10.478 -    case OID_GEN_TRANSMIT_BLOCK_SIZE:
  10.479 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.480 -      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
  10.481 -      break;
  10.482 -    case OID_GEN_RECEIVE_BLOCK_SIZE:
  10.483 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.484 -      KdPrint(("Unsupported set OID_GEN_RECEIVE_BLOCK_SIZE\n"));
  10.485 -      break;
  10.486 -    case OID_GEN_VENDOR_ID:
  10.487 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.488 -      KdPrint(("Unsupported set OID_GEN_VENDOR_ID\n"));
  10.489 -      break;
  10.490 -    case OID_GEN_VENDOR_DESCRIPTION:
  10.491 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.492 -      KdPrint(("Unsupported set OID_GEN_VENDOR_DESCRIPTION\n"));
  10.493 -      break;
  10.494 -    case OID_GEN_CURRENT_PACKET_FILTER:
  10.495 -      KdPrint(("Set OID_GEN_CURRENT_PACKET_FILTER (xi = %p)\n", xi));
  10.496 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_DIRECTED)
  10.497 -        KdPrint(("  NDIS_PACKET_TYPE_DIRECTED\n"));
  10.498 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_MULTICAST)
  10.499 -        KdPrint(("  NDIS_PACKET_TYPE_MULTICAST\n"));
  10.500 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_MULTICAST)
  10.501 -        KdPrint(("  NDIS_PACKET_TYPE_ALL_MULTICAST\n"));
  10.502 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_BROADCAST)
  10.503 -        KdPrint(("  NDIS_PACKET_TYPE_BROADCAST\n"));
  10.504 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_PROMISCUOUS)
  10.505 -        KdPrint(("  NDIS_PACKET_TYPE_PROMISCUOUS\n"));
  10.506 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
  10.507 -        KdPrint(("  NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n"));
  10.508 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_ALL_LOCAL)
  10.509 -        KdPrint(("  NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n"));  
  10.510 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_FUNCTIONAL)
  10.511 -        KdPrint(("  NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n"));
  10.512 -      if (*(ULONG *)data & NDIS_PACKET_TYPE_GROUP)
  10.513 -        KdPrint(("  NDIS_PACKET_TYPE_GROUP (not supported)\n"));
  10.514 -      if (*(ULONG *)data & ~SUPPORTED_PACKET_FILTERS)
  10.515 -      {
  10.516 -        status = NDIS_STATUS_NOT_SUPPORTED;
  10.517 -        KdPrint(("  returning NDIS_STATUS_NOT_SUPPORTED\n"));
  10.518 -        break;
  10.519 -      }
  10.520 -      xi->packet_filter = *(ULONG *)data;
  10.521 -      status = NDIS_STATUS_SUCCESS;
  10.522 -      break;
  10.523 -    case OID_GEN_CURRENT_LOOKAHEAD:
  10.524 -      xi->current_lookahead = *(ULONG *)data;
  10.525 -      KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi));
  10.526 -      status = NDIS_STATUS_SUCCESS;
  10.527 -      break;
  10.528 -    case OID_GEN_DRIVER_VERSION:
  10.529 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.530 -      KdPrint(("Unsupported set OID_GEN_DRIVER_VERSION\n"));
  10.531 -      break;
  10.532 -    case OID_GEN_MAXIMUM_TOTAL_SIZE:
  10.533 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.534 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
  10.535 -      break;
  10.536 -    case OID_GEN_PROTOCOL_OPTIONS:
  10.537 -      KdPrint(("Unsupported set OID_GEN_PROTOCOL_OPTIONS\n"));
  10.538 -      // TODO - actually do this...
  10.539 -      status = NDIS_STATUS_SUCCESS;
  10.540 -      break;
  10.541 -    case OID_GEN_MAC_OPTIONS:
  10.542 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.543 -      KdPrint(("Unsupported set OID_GEN_MAC_OPTIONS\n"));
  10.544 -      break;
  10.545 -    case OID_GEN_MEDIA_CONNECT_STATUS:
  10.546 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.547 -      KdPrint(("Unsupported set OID_GEN_MEDIA_CONNECT_STATUS\n"));
  10.548 -      break;
  10.549 -    case OID_GEN_MAXIMUM_SEND_PACKETS:
  10.550 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.551 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_SEND_PACKETS\n"));
  10.552 -      break;
  10.553 -    case OID_GEN_XMIT_OK:
  10.554 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.555 -      KdPrint(("Unsupported set OID_GEN_XMIT_OK\n"));
  10.556 -      break;
  10.557 -    case OID_GEN_RCV_OK:
  10.558 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.559 -      KdPrint(("Unsupported set OID_GEN_RCV_OK\n"));
  10.560 -      break;
  10.561 -    case OID_GEN_XMIT_ERROR:
  10.562 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.563 -      KdPrint(("Unsupported set OID_GEN_XMIT_ERROR\n"));
  10.564 -      break;
  10.565 -    case OID_GEN_RCV_ERROR:
  10.566 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.567 -      KdPrint(("Unsupported set OID_GEN_RCV_ERROR\n"));
  10.568 -      break;
  10.569 -    case OID_GEN_RCV_NO_BUFFER:
  10.570 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.571 -      KdPrint(("Unsupported set OID_GEN_RCV_NO_BUFFER\n"));
  10.572 -      break;
  10.573 -    case OID_802_3_PERMANENT_ADDRESS:
  10.574 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.575 -      KdPrint(("Unsupported set OID_802_3_PERMANENT_ADDRESS\n"));
  10.576 -      break;
  10.577 -    case OID_802_3_CURRENT_ADDRESS:
  10.578 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.579 -      KdPrint(("Unsupported set OID_802_3_CURRENT_ADDRESS\n"));
  10.580 -      break;
  10.581 -    case OID_802_3_MULTICAST_LIST:
  10.582 -      KdPrint(("     Set OID_802_3_MULTICAST_LIST\n"));
  10.583 -      KdPrint(("       Length = %d\n", InformationBufferLength));
  10.584 -      KdPrint(("       Entries = %d\n", InformationBufferLength / 6));
  10.585 -      if (InformationBufferLength > MULTICAST_LIST_MAX_SIZE * 6)
  10.586 -      {
  10.587 -        status = NDIS_STATUS_MULTICAST_FULL;
  10.588 -        break;
  10.589 -      }
  10.590 -      
  10.591 -      if (InformationBufferLength % 6 != 0)
  10.592 -      {
  10.593 -        status = NDIS_STATUS_MULTICAST_FULL;
  10.594 -        break;
  10.595 -      }
  10.596 -      multicast_list = InformationBuffer;
  10.597 -      for (i = 0; i < InformationBufferLength / 6; i++)
  10.598 -      {
  10.599 -        if (!(multicast_list[i * 6 + 0] & 0x01))
  10.600 -        {
  10.601 -          KdPrint(("       Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i,
  10.602 -            (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1], 
  10.603 -            (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3], 
  10.604 -            (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]));
  10.605 -          /* the docs say that we should return NDIS_STATUS_MULTICAST_FULL if we get an invalid multicast address but I'm not sure if that's the case... */
  10.606 -        }
  10.607 -      }
  10.608 -      memcpy(xi->multicast_list, InformationBuffer, InformationBufferLength);
  10.609 -      xi->multicast_list_size = InformationBufferLength / 6;
  10.610 -      status = NDIS_STATUS_SUCCESS;
  10.611 -      break;
  10.612 -    case OID_802_3_MAXIMUM_LIST_SIZE:
  10.613 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.614 -      KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
  10.615 -      break;
  10.616 -    case OID_TCP_TASK_OFFLOAD:
  10.617 -      status = NDIS_STATUS_SUCCESS;
  10.618 -      KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
  10.619 -      // we should disable everything here, then enable what has been set
  10.620 -      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
  10.621 -      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION)
  10.622 -      {
  10.623 -        KdPrint(("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION));
  10.624 -        status = NDIS_STATUS_INVALID_DATA;
  10.625 -        break;
  10.626 -      }
  10.627 -      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER))
  10.628 -      {
  10.629 -        KdPrint(("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER)));
  10.630 -        status = NDIS_STATUS_INVALID_DATA;
  10.631 -        break;
  10.632 -      }
  10.633 -      *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  10.634 -      offset = ntoh->OffsetFirstTask;
  10.635 -      nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
  10.636 -      while (offset != 0)
  10.637 -      {
  10.638 -        *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
  10.639 -        nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
  10.640 -        switch (nto->Task)
  10.641 -        {
  10.642 -        case TcpIpChecksumNdisTask:
  10.643 -          *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  10.644 -          nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
  10.645 -          KdPrint(("TcpIpChecksumNdisTask\n"));
  10.646 -          KdPrint(("  V4Transmit.IpOptionsSupported  = %d\n", nttic->V4Transmit.IpOptionsSupported));
  10.647 -          KdPrint(("  V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported));
  10.648 -          KdPrint(("  V4Transmit.TcpChecksum         = %d\n", nttic->V4Transmit.TcpChecksum));
  10.649 -          KdPrint(("  V4Transmit.UdpChecksum         = %d\n", nttic->V4Transmit.UdpChecksum));
  10.650 -          KdPrint(("  V4Transmit.IpChecksum          = %d\n", nttic->V4Transmit.IpChecksum));
  10.651 -          KdPrint(("  V4Receive.IpOptionsSupported   = %d\n", nttic->V4Receive.IpOptionsSupported));
  10.652 -          KdPrint(("  V4Receive.TcpOptionsSupported  = %d\n", nttic->V4Receive.TcpOptionsSupported));
  10.653 -          KdPrint(("  V4Receive.TcpChecksum          = %d\n", nttic->V4Receive.TcpChecksum));
  10.654 -          KdPrint(("  V4Receive.UdpChecksum          = %d\n", nttic->V4Receive.UdpChecksum));
  10.655 -          KdPrint(("  V4Receive.IpChecksum           = %d\n", nttic->V4Receive.IpChecksum));
  10.656 -          KdPrint(("  V6Transmit.IpOptionsSupported  = %d\n", nttic->V6Transmit.IpOptionsSupported));
  10.657 -          KdPrint(("  V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported));
  10.658 -          KdPrint(("  V6Transmit.TcpChecksum         = %d\n", nttic->V6Transmit.TcpChecksum));
  10.659 -          KdPrint(("  V6Transmit.UdpChecksum         = %d\n", nttic->V6Transmit.UdpChecksum));
  10.660 -          KdPrint(("  V6Receive.IpOptionsSupported   = %d\n", nttic->V6Receive.IpOptionsSupported));
  10.661 -          KdPrint(("  V6Receive.TcpOptionsSupported  = %d\n", nttic->V6Receive.TcpOptionsSupported));
  10.662 -          KdPrint(("  V6Receive.TcpChecksum          = %d\n", nttic->V6Receive.TcpChecksum));
  10.663 -          KdPrint(("  V6Receive.UdpChecksum          = %d\n", nttic->V6Receive.UdpChecksum));
  10.664 -          /* check for stuff we outright don't support */
  10.665 -          if (nttic->V6Transmit.IpOptionsSupported ||
  10.666 -            nttic->V6Transmit.TcpOptionsSupported ||
  10.667 -            nttic->V6Transmit.TcpChecksum ||
  10.668 -            nttic->V6Transmit.UdpChecksum ||
  10.669 -            nttic->V6Receive.IpOptionsSupported ||
  10.670 -            nttic->V6Receive.TcpOptionsSupported ||
  10.671 -            nttic->V6Receive.TcpChecksum ||
  10.672 -            nttic->V6Receive.UdpChecksum)
  10.673 -          {
  10.674 -            KdPrint(("IPv6 offload not supported\n"));
  10.675 -            status = NDIS_STATUS_INVALID_DATA;
  10.676 -            nttic = NULL;
  10.677 -            break;
  10.678 -          }
  10.679 -          if (nttic->V4Transmit.IpOptionsSupported ||
  10.680 -            nttic->V4Transmit.IpChecksum)
  10.681 -          {
  10.682 -            KdPrint(("IPv4 IP Transmit offload not supported\n"));
  10.683 -            status = NDIS_STATUS_INVALID_DATA;
  10.684 -            nttic = NULL;
  10.685 -            break;
  10.686 -          }
  10.687 -          if (nttic->V4Receive.IpOptionsSupported &&
  10.688 -            !nttic->V4Receive.IpChecksum)
  10.689 -          {
  10.690 -            KdPrint(("Invalid combination\n"));
  10.691 -            status = NDIS_STATUS_INVALID_DATA;
  10.692 -            nttic = NULL;
  10.693 -            break;
  10.694 -          }
  10.695 -          if (nttic->V4Transmit.TcpOptionsSupported &&
  10.696 -            !nttic->V4Transmit.TcpChecksum)
  10.697 -          {
  10.698 -            KdPrint(("Invalid combination\n"));
  10.699 -            status = NDIS_STATUS_INVALID_DATA;
  10.700 -            nttic = NULL;
  10.701 -            break;
  10.702 -          }
  10.703 -          if (nttic->V4Receive.TcpOptionsSupported &&
  10.704 -            !nttic->V4Receive.TcpChecksum)
  10.705 -          {
  10.706 -            KdPrint(("Invalid combination\n"));
  10.707 -            status = NDIS_STATUS_INVALID_DATA;
  10.708 -            nttic = NULL;
  10.709 -            break;
  10.710 -          }
  10.711 -          break;
  10.712 -        case TcpLargeSendNdisTask:
  10.713 -          *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND);
  10.714 -          KdPrint(("TcpLargeSendNdisTask\n"));
  10.715 -          nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
  10.716 -          KdPrint(("  MaxOffLoadSize                 = %d\n", nttls->MaxOffLoadSize));
  10.717 -          KdPrint(("  MinSegmentCount                = %d\n", nttls->MinSegmentCount));
  10.718 -          KdPrint(("  TcpOptions                     = %d\n", nttls->TcpOptions));
  10.719 -          KdPrint(("  IpOptions                      = %d\n", nttls->IpOptions));
  10.720 -          if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS)
  10.721 -          {
  10.722 -            KdPrint(("     MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS));
  10.723 -            status = NDIS_STATUS_INVALID_DATA;
  10.724 -            nttls = NULL;
  10.725 -            break;
  10.726 -          }
  10.727 -          if (nttls->IpOptions)
  10.728 -          {
  10.729 -            KdPrint(("     IpOptions not supported\n"));
  10.730 -            status = NDIS_STATUS_INVALID_DATA;
  10.731 -            nttls = NULL;
  10.732 -            break;
  10.733 -          }
  10.734 -          if (nttls->TcpOptions)
  10.735 -          {
  10.736 -            KdPrint(("     TcpOptions not supported\n"));
  10.737 -            status = NDIS_STATUS_INVALID_DATA;
  10.738 -            nttls = NULL;
  10.739 -            break;
  10.740 -          }
  10.741 -          break;
  10.742 -        default:
  10.743 -          KdPrint(("     Unknown Task %d\n", nto->Task));
  10.744 -        }
  10.745 -        offset = nto->OffsetNextTask;
  10.746 -      }
  10.747 -      if (nttic != NULL)
  10.748 -        xi->setting_csum = *nttic;
  10.749 -      else
  10.750 -      {
  10.751 -        RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
  10.752 -        KdPrint(("     csum offload disabled\n", nto->Task));
  10.753 -      }        
  10.754 -      if (nttls != NULL)
  10.755 -        xi->setting_max_offload = nttls->MaxOffLoadSize;
  10.756 -      else
  10.757 -      {
  10.758 -        xi->setting_max_offload = 0;
  10.759 -        KdPrint(("     LSO disabled\n", nto->Task));
  10.760 -      }
  10.761 -      break;
  10.762 -    case OID_PNP_SET_POWER:
  10.763 -      KdPrint(("     Set OID_PNP_SET_POWER\n"));
  10.764 -      xi->new_power_state = *(PNDIS_DEVICE_POWER_STATE)InformationBuffer;
  10.765 -      IoQueueWorkItem(xi->power_workitem, XenNet_SetPower, DelayedWorkQueue, xi);
  10.766 -      status = NDIS_STATUS_PENDING;
  10.767 -      break;
  10.768 -    default:
  10.769 -      KdPrint(("Set Unknown OID 0x%x\n", Oid));
  10.770 -      status = NDIS_STATUS_NOT_SUPPORTED;
  10.771 -      break;
  10.772 -  }
  10.773 -  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  10.774 -  return status;
  10.775 -}
  10.776 +#ifdef _GPLPV_NDIS5
  10.777 +#include "xennet5_oid.c"
  10.778 +#else
  10.779 +#include "xennet6_oid.c"
  10.780 +#endif
    11.1 --- a/xennet/xennet_rx.c	Sat Apr 30 00:24:01 2011 +1000
    11.2 +++ b/xennet/xennet_rx.c	Sat Apr 30 10:57:23 2011 +1000
    11.3 @@ -1,1160 +1,5 @@
    11.4 -/*
    11.5 -PV Net Driver for Windows Xen HVM Domains
    11.6 -Copyright (C) 2007 James Harper
    11.7 -Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
    11.8 -
    11.9 -This program is free software; you can redistribute it and/or
   11.10 -modify it under the terms of the GNU General Public License
   11.11 -as published by the Free Software Foundation; either version 2
   11.12 -of the License, or (at your option) any later version.
   11.13 -
   11.14 -This program is distributed in the hope that it will be useful,
   11.15 -but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.17 -GNU General Public License for more details.
   11.18 -
   11.19 -You should have received a copy of the GNU General Public License
   11.20 -along with this program; if not, write to the Free Software
   11.21 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   11.22 -*/
   11.23 -
   11.24 -#include "xennet.h"
   11.25 -
   11.26 -static LONG rx_pb_outstanding = 0;
   11.27 -
   11.28 -static __inline shared_buffer_t *
   11.29 -get_pb_from_freelist(struct xennet_info *xi)
   11.30 -{
   11.31 -  NDIS_STATUS status;
   11.32 -  shared_buffer_t *pb;
   11.33 -  PVOID ptr_ref;
   11.34 -
   11.35 -  if (stack_pop(xi->rx_pb_stack, &ptr_ref))
   11.36 -  {
   11.37 -    pb = ptr_ref;
   11.38 -    pb->ref_count = 1;
   11.39 -    InterlockedDecrement(&xi->rx_pb_free);
   11.40 -    InterlockedIncrement(&rx_pb_outstanding);
   11.41 -    return pb;
   11.42 -  }
   11.43 -
   11.44 -  /* don't allocate a new one if we are shutting down */
   11.45 -  if (xi->shutting_down)
   11.46 -    return NULL;
   11.47 -    
   11.48 -  status = NdisAllocateMemoryWithTag(&pb, sizeof(shared_buffer_t), XENNET_POOL_TAG);
   11.49 -  if (status != STATUS_SUCCESS)
   11.50 -  {
   11.51 -    return NULL;
   11.52 -  }
   11.53 -  status = NdisAllocateMemoryWithTag(&pb->virtual, PAGE_SIZE, XENNET_POOL_TAG);
   11.54 -  if (status != STATUS_SUCCESS)
   11.55 -  {
   11.56 -    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
   11.57 -    return NULL;
   11.58 -  }
   11.59 -  pb->gref = (grant_ref_t)xi->vectors.GntTbl_GrantAccess(xi->vectors.context, 0,
   11.60 -            (ULONG)(MmGetPhysicalAddress(pb->virtual).QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, (ULONG)'XNRX');
   11.61 -  if (pb->gref == INVALID_GRANT_REF)
   11.62 -  {
   11.63 -    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
   11.64 -    NdisFreeMemory(pb->virtual, PAGE_SIZE, 0);
   11.65 -    return NULL;
   11.66 -  }
   11.67 -  pb->offset = (USHORT)(ULONG_PTR)pb->virtual & (PAGE_SIZE - 1);
   11.68 -  NdisAllocateBuffer(&status, &pb->buffer, xi->rx_buffer_pool, (PUCHAR)pb->virtual, PAGE_SIZE);
   11.69 -  if (status != STATUS_SUCCESS)
   11.70 -  {
   11.71 -    xi->vectors.GntTbl_EndAccess(xi->vectors.context,
   11.72 -        pb->gref, FALSE, (ULONG)'XNRX');
   11.73 -    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
   11.74 -    NdisFreeMemory(pb->virtual, PAGE_SIZE, 0);
   11.75 -    return NULL;
   11.76 -  }
   11.77 -  InterlockedIncrement(&rx_pb_outstanding);
   11.78 -  pb->ref_count = 1;
   11.79 -  return pb;
   11.80 -}
   11.81 -
   11.82 -static __inline VOID
   11.83 -ref_pb(struct xennet_info *xi, shared_buffer_t *pb)
   11.84 -{
   11.85 -  UNREFERENCED_PARAMETER(xi);
   11.86 -  InterlockedIncrement(&pb->ref_count);
   11.87 -}
   11.88 -
   11.89 -static __inline VOID
   11.90 -put_pb_on_freelist(struct xennet_info *xi, shared_buffer_t *pb)
   11.91 -{
   11.92 -  if (InterlockedDecrement(&pb->ref_count) == 0)
   11.93 -  {
   11.94 -    NdisAdjustBufferLength(pb->buffer, PAGE_SIZE);
   11.95 -    NDIS_BUFFER_LINKAGE(pb->buffer) = NULL;
   11.96 -    pb->next = NULL;
   11.97 -    stack_push(xi->rx_pb_stack, pb);
   11.98 -    InterlockedIncrement(&xi->rx_pb_free);
   11.99 -    InterlockedDecrement(&rx_pb_outstanding);
  11.100 -  }
  11.101 -}
  11.102 -
  11.103 -// Called at DISPATCH_LEVEL with rx lock held
  11.104 -static NDIS_STATUS
  11.105 -XenNet_FillRing(struct xennet_info *xi)
  11.106 -{
  11.107 -  unsigned short id;
  11.108 -  shared_buffer_t *page_buf;
  11.109 -  ULONG i, notify;
  11.110 -  ULONG batch_target;
  11.111 -  RING_IDX req_prod = xi->rx.req_prod_pvt;
  11.112 -  netif_rx_request_t *req;
  11.113 -
  11.114 -  //FUNCTION_ENTER();
  11.115 -
  11.116 -  batch_target = xi->rx_target - (req_prod - xi->rx.rsp_cons);
  11.117 -
  11.118 -  if (batch_target < (xi->rx_target >> 2))
  11.119 -  {
  11.120 -    //FUNCTION_EXIT();
  11.121 -    return NDIS_STATUS_SUCCESS; /* only refill if we are less than 3/4 full already */
  11.122 -  }
  11.123 -
  11.124 -  for (i = 0; i < batch_target; i++)
  11.125 -  {
  11.126 -    page_buf = get_pb_from_freelist(xi);
  11.127 -    if (!page_buf)
  11.128 -    {
  11.129 -      KdPrint((__DRIVER_NAME "     Added %d out of %d buffers to rx ring (no free pages)\n", i, batch_target));
  11.130 -      break;
  11.131 -    }
  11.132 -    xi->rx_id_free--;
  11.133 -
  11.134 -    /* Give to netback */
  11.135 -    id = (USHORT)((req_prod + i) & (NET_RX_RING_SIZE - 1));
  11.136 -    ASSERT(xi->rx_ring_pbs[id] == NULL);
  11.137 -    xi->rx_ring_pbs[id] = page_buf;
  11.138 -    req = RING_GET_REQUEST(&xi->rx, req_prod + i);
  11.139 -    req->id = id;
  11.140 -    req->gref = page_buf->gref;
  11.141 -    ASSERT(req->gref != INVALID_GRANT_REF);
  11.142 -  }
  11.143 -  KeMemoryBarrier();
  11.144 -  xi->rx.req_prod_pvt = req_prod + i;
  11.145 -  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->rx, notify);
  11.146 -  if (notify)
  11.147 -  {
  11.148 -    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->event_channel);
  11.149 -  }
  11.150 -
  11.151 -  //FUNCTION_EXIT();
  11.152 -
  11.153 -  return NDIS_STATUS_SUCCESS;
  11.154 -}
  11.155 -
  11.156 -LONG total_allocated_packets = 0;
  11.157 -LONG dpc_limit_hit = 0;
  11.158 -LONG resource_packets = 0;
  11.159 -LARGE_INTEGER last_print_time;
  11.160 -
  11.161 -/* lock free */
  11.162 -static PNDIS_PACKET
  11.163 -get_packet_from_freelist(struct xennet_info *xi)
  11.164 -{
  11.165 -  NDIS_STATUS status;
  11.166 -  PNDIS_PACKET packet;
  11.167 -  PVOID ptr_ref;
  11.168 -
  11.169 -  if (stack_pop(xi->rx_packet_stack, &ptr_ref))
  11.170 -  {
  11.171 -    packet = ptr_ref;
  11.172 -    InterlockedIncrement(&total_allocated_packets);
  11.173 -    return packet;
  11.174 -  }
  11.175 -  
  11.176 -  if (xi->rx_shutting_down) /* don't keep allocating new packets on shutdown */
  11.177 -    return NULL;
  11.178 -
  11.179 -  NdisAllocatePacket(&status, &packet, xi->rx_packet_pool);
  11.180 -  if (status != NDIS_STATUS_SUCCESS)
  11.181 -  {
  11.182 -    KdPrint((__DRIVER_NAME "     cannot allocate packet\n"));
  11.183 -    return NULL;
  11.184 -  }
  11.185 -  NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
  11.186 -  NdisZeroMemory(packet->MiniportReservedEx, sizeof(packet->MiniportReservedEx));
  11.187 -  InterlockedIncrement(&total_allocated_packets);
  11.188 -  return packet;
  11.189 -}
  11.190 -
  11.191 -/* lock free */
  11.192 -static VOID
  11.193 -put_packet_on_freelist(struct xennet_info *xi, PNDIS_PACKET packet)
  11.194 -{
  11.195 -  LARGE_INTEGER current_time;
  11.196 -  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
  11.197 -
  11.198 -  UNREFERENCED_PARAMETER(xi);
  11.199 -  
  11.200 -  InterlockedDecrement(&total_allocated_packets);
  11.201 -
  11.202 -  NdisReinitializePacket(packet);
  11.203 -  RtlZeroMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(packet), sizeof(NDIS_PACKET_EXTENSION));
  11.204 -  csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
  11.205 -    packet, TcpIpChecksumPacketInfo);
  11.206 -  csum_info->Value = 0;
  11.207 -
  11.208 -  stack_push(xi->rx_packet_stack, packet);
  11.209 -
  11.210 -  KeQuerySystemTime(&current_time);
  11.211 -  if ((current_time.QuadPart - last_print_time.QuadPart) / 10000 > 5000)
  11.212 -  {
  11.213 -    last_print_time.QuadPart = current_time.QuadPart;
  11.214 -    KdPrint(("total_allocated_packets = %d, rx_outstanding = %d, resource_packets = %d, dpc_limit_hit = %d, rx_pb_outstanding = %d, rx_pb_free = %d\n", total_allocated_packets, xi->rx_outstanding, resource_packets, dpc_limit_hit, rx_pb_outstanding, xi->rx_pb_free));
  11.215 -  }
  11.216 -}
  11.217 -
  11.218 -static PNDIS_PACKET
  11.219 -XenNet_MakePacket(struct xennet_info *xi, packet_info_t *pi)
  11.220 -{
  11.221 -  NDIS_STATUS status;
  11.222 -  PNDIS_PACKET packet;
  11.223 -  PNDIS_BUFFER out_buffer;
  11.224 -  USHORT new_ip4_length;
  11.225 -  PUCHAR header_va;
  11.226 -  ULONG out_remaining;
  11.227 -  ULONG tcp_length;
  11.228 -  ULONG header_extra;
  11.229 -  shared_buffer_t *header_buf;
  11.230 -
  11.231 -  //FUNCTION_ENTER();
  11.232 -  
  11.233 -  packet = get_packet_from_freelist(xi);
  11.234 -  if (packet == NULL)
  11.235 -  {
  11.236 -    /* buffers will be freed in MakePackets */
  11.237 -    //KdPrint((__DRIVER_NAME "     No free packets\n"));
  11.238 -    //FUNCTION_EXIT();
  11.239 -    return NULL;
  11.240 -  }
  11.241 -  
  11.242 -  header_buf = NdisAllocateFromNPagedLookasideList(&xi->rx_lookaside_list);
  11.243 -  if (!header_buf)
  11.244 -  {
  11.245 -    KdPrint((__DRIVER_NAME "     No free header buffers\n"));
  11.246 -    put_packet_on_freelist(xi, packet);
  11.247 -    return NULL;
  11.248 -  }
  11.249 -  header_va = (PUCHAR)(header_buf + 1);
  11.250 -  NdisZeroMemory(header_buf, sizeof(shared_buffer_t));
  11.251 -  NdisMoveMemory(header_va, pi->header, pi->header_length);
  11.252 -  //KdPrint((__DRIVER_NAME "     header_length = %d, current_lookahead = %d\n", pi->header_length, xi->current_lookahead));
  11.253 -  //KdPrint((__DRIVER_NAME "     ip4_header_length = %d\n", pi->ip4_header_length));
  11.254 -  //KdPrint((__DRIVER_NAME "     tcp_header_length = %d\n", pi->tcp_header_length));
  11.255 -  /* make sure we satisfy the lookahead requirement */
  11.256 -  
  11.257 -  if (pi->split_required)
  11.258 -  {
  11.259 -    /* for split packets we need to make sure the 'header' is no bigger than header+mss bytes */
  11.260 -    XenNet_BuildHeader(pi, header_va, min((ULONG)MAX_ETH_HEADER_LENGTH + pi->ip4_header_length + pi->tcp_header_length + pi->mss, MAX_ETH_HEADER_LENGTH + max(MIN_LOOKAHEAD_LENGTH, xi->current_lookahead)));
  11.261 -  }
  11.262 -  else
  11.263 -  {
  11.264 -    XenNet_BuildHeader(pi, header_va, max(MIN_LOOKAHEAD_LENGTH, xi->current_lookahead) + MAX_ETH_HEADER_LENGTH);
  11.265 -  }
  11.266 -  header_extra = pi->header_length - (MAX_ETH_HEADER_LENGTH + pi->ip4_header_length + pi->tcp_header_length);
  11.267 -  ASSERT(pi->header_length <= MAX_ETH_HEADER_LENGTH + MAX_LOOKAHEAD_LENGTH);
  11.268 -  NdisAllocateBuffer(&status, &out_buffer, xi->rx_buffer_pool, header_va, pi->header_length);
  11.269 -  if (status != STATUS_SUCCESS)
  11.270 -  {
  11.271 -    KdPrint((__DRIVER_NAME "     No free header buffers\n"));
  11.272 -    NdisFreeToNPagedLookasideList(&xi->rx_lookaside_list, header_buf);
  11.273 -    put_packet_on_freelist(xi, packet);
  11.274 -    return NULL;
  11.275 -  }
  11.276 -  NdisChainBufferAtBack(packet, out_buffer);
  11.277 -  *(shared_buffer_t **)&packet->MiniportReservedEx[0] = header_buf;
  11.278 -  header_buf->next = pi->curr_pb;
  11.279 -
  11.280 -  // TODO: if there are only a few bytes left on the first buffer then add them to the header buffer too... maybe
  11.281 -
  11.282 -  if (pi->split_required)
  11.283 -  {
  11.284 -    tcp_length = (USHORT)min(pi->mss, pi->tcp_remaining);
  11.285 -    new_ip4_length = (USHORT)(pi->ip4_header_length + pi->tcp_header_length + tcp_length);
  11.286 -    //KdPrint((__DRIVER_NAME "     new_ip4_length = %d\n", new_ip4_length));
  11.287 -    //KdPrint((__DRIVER_NAME "     this tcp_length = %d\n", tcp_length));
  11.288 -    SET_NET_USHORT(&header_va[XN_HDR_SIZE + 2], new_ip4_length);
  11.289 -    SET_NET_ULONG(&header_va[XN_HDR_SIZE + pi->ip4_header_length + 4], pi->tcp_seq);
  11.290 -    pi->tcp_seq += tcp_length;
  11.291 -    pi->tcp_remaining = (USHORT)(pi->tcp_remaining - tcp_length);
  11.292 -    /* part of the packet is already present in the header buffer for lookahead */
  11.293 -    out_remaining = tcp_length - header_extra;
  11.294 -    ASSERT((LONG)out_remaining >= 0);
  11.295 -  }
  11.296 -  else
  11.297 -  {
  11.298 -    out_remaining = pi->total_length - pi->header_length;
  11.299 -    ASSERT((LONG)out_remaining >= 0);
  11.300 -  }
  11.301 -  //KdPrint((__DRIVER_NAME "     before loop - out_remaining = %d\n", out_remaining));
  11.302 -
  11.303 -  NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_RESOURCES); /* for packets only containing a header buffer - see Indicate*/
  11.304 -  while (out_remaining != 0)
  11.305 -  {
  11.306 -    ULONG in_buffer_offset;
  11.307 -    ULONG in_buffer_length;
  11.308 -    ULONG out_length;
  11.309 -    
  11.310 -    NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS); /* packet contains additional buffers */
  11.311 -    //KdPrint((__DRIVER_NAME "     in loop - out_remaining = %d, curr_buffer = %p, curr_pb = %p\n", out_remaining, pi->curr_buffer, pi->curr_pb));
  11.312 -    if (!pi->curr_buffer || !pi->curr_pb)
  11.313 -    {
  11.314 -      KdPrint((__DRIVER_NAME "     out of buffers for packet\n"));
  11.315 -      KdPrint((__DRIVER_NAME "     out_remaining = %d, curr_buffer = %p, curr_pb = %p\n", out_remaining, pi->curr_buffer, pi->curr_pb));
  11.316 -      // TODO: free some stuff or we'll leak
  11.317 -      /* unchain buffers then free packet */
  11.318 -      return NULL;
  11.319 -    }
  11.320 -    NdisQueryBufferOffset(pi->curr_buffer, &in_buffer_offset, &in_buffer_length);
  11.321 -    out_length = min(out_remaining, in_buffer_length - pi->curr_mdl_offset);
  11.322 -    NdisCopyBuffer(&status, &out_buffer, xi->rx_buffer_pool, pi->curr_buffer, pi->curr_mdl_offset, out_length);
  11.323 -    ASSERT(status == STATUS_SUCCESS); //TODO: properly handle error
  11.324 -    NdisChainBufferAtBack(packet, out_buffer);
  11.325 -    ref_pb(xi, pi->curr_pb);
  11.326 -    pi->curr_mdl_offset = (USHORT)(pi->curr_mdl_offset + out_length);
  11.327 -    if (pi->curr_mdl_offset == in_buffer_length)
  11.328 -    {
  11.329 -      NdisGetNextBuffer(pi->curr_buffer, &pi->curr_buffer);
  11.330 -      pi->curr_pb = pi->curr_pb->next;
  11.331 -      pi->curr_mdl_offset = 0;
  11.332 -    }
  11.333 -    out_remaining -= out_length;
  11.334 -  }
  11.335 -  if (pi->split_required)
  11.336 -  {
  11.337 -    XenNet_SumIpHeader(header_va, pi->ip4_header_length);
  11.338 -  }
  11.339 -  if (header_extra > 0)
  11.340 -    pi->header_length -= header_extra;
  11.341 -  ASSERT(*(shared_buffer_t **)&packet->MiniportReservedEx[0]);
  11.342 -  //FUNCTION_EXIT();
  11.343 -  return packet;
  11.344 -}
  11.345 -
  11.346 -/*
  11.347 - Windows appears to insist that the checksum on received packets is correct, and won't
  11.348 - believe us when we lie about it, which happens when the packet is generated on the
  11.349 - same bridge in Dom0. Doh!
  11.350 - This is only for TCP and UDP packets. IP checksums appear to be correct anyways.
  11.351 -*/
  11.352 -
  11.353 -static BOOLEAN
  11.354 -XenNet_SumPacketData(
  11.355 -  packet_info_t *pi,
  11.356 -  PNDIS_PACKET packet,
  11.357 -  BOOLEAN set_csum
  11.358 -)
  11.359 -{
  11.360 -  USHORT i;
  11.361 -  PUCHAR buffer;
  11.362 -  PMDL mdl;
  11.363 -  UINT total_length;
  11.364 -  UINT data_length;
  11.365 -  UINT buffer_length;
  11.366 -  USHORT buffer_offset;
  11.367 -  ULONG csum;
  11.368 -  PUSHORT csum_ptr;
  11.369 -  USHORT remaining;
  11.370 -  USHORT ip4_length;
  11.371 -  BOOLEAN csum_span = TRUE; /* when the USHORT to be checksummed spans a buffer */
  11.372 -  
  11.373 -  //FUNCTION_ENTER();
  11.374 -
  11.375 -  NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
  11.376 -  ASSERT(mdl);
  11.377 -
  11.378 -  ip4_length = GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 2]);
  11.379 -  data_length = ip4_length + XN_HDR_SIZE;
  11.380 -  
  11.381 -  if ((USHORT)data_length > total_length)
  11.382 -  {
  11.383 -    KdPrint((__DRIVER_NAME "     Size Mismatch %d (ip4_length + XN_HDR_SIZE) != %d (total_length)\n", ip4_length + XN_HDR_SIZE, total_length));
  11.384 -    return FALSE;
  11.385 -  }
  11.386 -
  11.387 -  switch (pi->ip_proto)
  11.388 -  {
  11.389 -  case 6:
  11.390 -    ASSERT(buffer_length >= (USHORT)(XN_HDR_SIZE + pi->ip4_header_length + 17));
  11.391 -    csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + pi->ip4_header_length + 16];
  11.392 -    break;
  11.393 -  case 17:
  11.394 -    ASSERT(buffer_length >= (USHORT)(XN_HDR_SIZE + pi->ip4_header_length + 7));
  11.395 -    csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + pi->ip4_header_length + 6];
  11.396 -    break;
  11.397 -  default:
  11.398 -    KdPrint((__DRIVER_NAME "     Don't know how to calc sum for IP Proto %d\n", pi->ip_proto));
  11.399 -    //FUNCTION_EXIT();
  11.400 -    return FALSE; // should never happen
  11.401 -  }
  11.402 -
  11.403 -  if (set_csum)  
  11.404 -    *csum_ptr = 0;
  11.405 -
  11.406 -  csum = 0;
  11.407 -  csum += GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 12]) + GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 14]); // src
  11.408 -  csum += GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 16]) + GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 18]); // dst
  11.409 -  csum += ((USHORT)buffer[XN_HDR_SIZE + 9]);
  11.410 -
  11.411 -  remaining = ip4_length - pi->ip4_header_length;
  11.412 -
  11.413 -  csum += remaining;
  11.414 -  
  11.415 -  csum_span = FALSE;
  11.416 -  buffer_offset = i = XN_HDR_SIZE + pi->ip4_header_length;
  11.417 -  while (i < data_length)
  11.418 -  {
  11.419 -    /* don't include the checksum field itself in the calculation */
  11.420 -    if ((pi->ip_proto == 6 && i == XN_HDR_SIZE + pi->ip4_header_length + 16) || (pi->ip_proto == 17 && i == XN_HDR_SIZE + pi->ip4_header_length + 6))
  11.421 -    {
  11.422 -      /* we know that this always happens in the header buffer so we are guaranteed the full two bytes */
  11.423 -      i += 2;
  11.424 -      buffer_offset += 2;
  11.425 -      continue;
  11.426 -    }
  11.427 -    if (csum_span)
  11.428 -    {
  11.429 -      /* the other half of the next bit */
  11.430 -      ASSERT(buffer_offset == 0);
  11.431 -      csum += (USHORT)buffer[buffer_offset];
  11.432 -      csum_span = FALSE;
  11.433 -      i += 1;
  11.434 -      buffer_offset += 1;
  11.435 -    }
  11.436 -    else if (buffer_offset == buffer_length - 1)
  11.437 -    {
  11.438 -      /* deal with a buffer ending on an odd byte boundary */
  11.439 -      csum += (USHORT)buffer[buffer_offset] << 8;
  11.440 -      csum_span = TRUE;
  11.441 -      i += 1;
  11.442 -      buffer_offset += 1;
  11.443 -    }
  11.444 -    else
  11.445 -    {
  11.446 -      csum += GET_NET_PUSHORT(&buffer[buffer_offset]);
  11.447 -      i += 2;
  11.448 -      buffer_offset += 2;
  11.449 -    }
  11.450 -    if (buffer_offset == buffer_length && i < total_length)
  11.451 -    {
  11.452 -      NdisGetNextBuffer(mdl, &mdl);
  11.453 -      if (mdl == NULL)
  11.454 -      {
  11.455 -        KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
  11.456 -        return FALSE; // should never happen
  11.457 -      }
  11.458 -      NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
  11.459 -      ASSERT(buffer_length);
  11.460 -      buffer_offset = 0;
  11.461 -    }
  11.462 -  }
  11.463 -      
  11.464 -  while (csum & 0xFFFF0000)
  11.465 -    csum = (csum & 0xFFFF) + (csum >> 16);
  11.466 -  
  11.467 -  if (set_csum)
  11.468 -  {
  11.469 -    *csum_ptr = (USHORT)~GET_NET_USHORT((USHORT)csum);
  11.470 -  }
  11.471 -  else
  11.472 -  {
  11.473 -    //FUNCTION_EXIT();
  11.474 -    return (BOOLEAN)(*csum_ptr == (USHORT)~GET_NET_USHORT((USHORT)csum));
  11.475 -  }
  11.476 -  //FUNCTION_EXIT();
  11.477 -  return TRUE;
  11.478 -}
  11.479 -
  11.480 -static ULONG
  11.481 -XenNet_MakePackets(
  11.482 -  struct xennet_info *xi,
  11.483 -  PLIST_ENTRY rx_packet_list,
  11.484 -  packet_info_t *pi
  11.485 -)
  11.486 -{
  11.487 -  ULONG packet_count = 0;
  11.488 -  PNDIS_PACKET packet;
  11.489 -  PLIST_ENTRY entry;
  11.490 -  UCHAR psh;
  11.491 -  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
  11.492 -  ULONG parse_result;  
  11.493 -  //PNDIS_BUFFER buffer;
  11.494 -  shared_buffer_t *page_buf;
  11.495 -
  11.496 -  //FUNCTION_ENTER();
  11.497 -
  11.498 -  parse_result = XenNet_ParsePacketHeader(pi, NULL, 0);
  11.499 -  
  11.500 -  if (!XenNet_FilterAcceptPacket(xi, pi))
  11.501 -  {
  11.502 -    goto done;
  11.503 -  }
  11.504 -
  11.505 -  switch (pi->ip_proto)
  11.506 -  {
  11.507 -  case 6:  // TCP
  11.508 -    if (pi->split_required)
  11.509 -      break;
  11.510 -    // fallthrough
  11.511 -  case 17:  // UDP
  11.512 -    packet = XenNet_MakePacket(xi, pi);
  11.513 -    if (packet == NULL)
  11.514 -    {
  11.515 -      //KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
  11.516 -      xi->stat_rx_no_buffer++;
  11.517 -      packet_count = 0;
  11.518 -      goto done;
  11.519 -    }
  11.520 -    if (parse_result == PARSE_OK)
  11.521 -    {
  11.522 -      BOOLEAN checksum_offload = FALSE;
  11.523 -      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
  11.524 -        packet, TcpIpChecksumPacketInfo);
  11.525 -      ASSERT(csum_info->Value == 0);
  11.526 -      if (pi->csum_blank || pi->data_validated)
  11.527 -      {
  11.528 -        if (xi->setting_csum.V4Receive.TcpChecksum && pi->ip_proto == 6)
  11.529 -        {
  11.530 -          if (!pi->tcp_has_options || xi->setting_csum.V4Receive.TcpOptionsSupported)
  11.531 -          {
  11.532 -            csum_info->Receive.NdisPacketIpChecksumSucceeded = TRUE;
  11.533 -            csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
  11.534 -            checksum_offload = TRUE;
  11.535 -          }
  11.536 -        }
  11.537 -        else if (xi->setting_csum.V4Receive.UdpChecksum && pi->ip_proto == 17)
  11.538 -        {
  11.539 -          csum_info->Receive.NdisPacketIpChecksumSucceeded = TRUE;
  11.540 -          csum_info->Receive.NdisPacketUdpChecksumSucceeded = TRUE;
  11.541 -          checksum_offload = TRUE;
  11.542 -        }
  11.543 -        if (pi->csum_blank && (!xi->config_csum_rx_dont_fix || !checksum_offload))
  11.544 -        {
  11.545 -          XenNet_SumPacketData(pi, packet, TRUE);
  11.546 -        }
  11.547 -      }
  11.548 -      else if (xi->config_csum_rx_check)
  11.549 -      {
  11.550 -        if (xi->setting_csum.V4Receive.TcpChecksum && pi->ip_proto == 6)
  11.551 -        {
  11.552 -          if (XenNet_SumPacketData(pi, packet, FALSE))
  11.553 -          {
  11.554 -            csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
  11.555 -          }
  11.556 -          else
  11.557 -          {
  11.558 -            csum_info->Receive.NdisPacketTcpChecksumFailed = TRUE;
  11.559 -          }
  11.560 -        } else if (xi->setting_csum.V4Receive.UdpChecksum && pi->ip_proto == 17)
  11.561 -        {
  11.562 -          if (XenNet_SumPacketData(pi, packet, FALSE))
  11.563 -          {
  11.564 -            csum_info->Receive.NdisPacketUdpChecksumSucceeded = TRUE;
  11.565 -          }
  11.566 -          else
  11.567 -          {
  11.568 -            csum_info->Receive.NdisPacketUdpChecksumFailed = TRUE;
  11.569 -          }
  11.570 -        }
  11.571 -      }
  11.572 -    }
  11.573 -    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
  11.574 -    InsertTailList(rx_packet_list, entry);
  11.575 -    packet_count = 1;
  11.576 -    goto done;
  11.577 -  default:
  11.578 -    packet = XenNet_MakePacket(xi, pi);
  11.579 -    if (packet == NULL)
  11.580 -    {
  11.581 -      //KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
  11.582 -      xi->stat_rx_no_buffer++;
  11.583 -      packet_count = 0;
  11.584 -      goto done;
  11.585 -    }
  11.586 -    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
  11.587 -    InsertTailList(rx_packet_list, entry);
  11.588 -    packet_count = 1;
  11.589 -    goto done;
  11.590 -  }
  11.591 -  
  11.592 -  pi->tcp_remaining = pi->tcp_length;
  11.593 -
  11.594 -  /* we can make certain assumptions here as the following code is only for tcp4 */
  11.595 -  psh = pi->header[XN_HDR_SIZE + pi->ip4_header_length + 13] & 8;
  11.596 -  while (pi->tcp_remaining)
  11.597 -  {
  11.598 -    PUCHAR header_va;
  11.599 -    PMDL mdl;
  11.600 -    UINT total_length;
  11.601 -    UINT buffer_length;
  11.602 -    packet = XenNet_MakePacket(xi, pi);
  11.603 -    if (!packet)
  11.604 -    {
  11.605 -      //KdPrint((__DRIVER_NAME "     Ran out of packets\n"));
  11.606 -      xi->stat_rx_no_buffer++;
  11.607 -      break; /* we are out of memory - just drop the packets */
  11.608 -    }
  11.609 -    if (xi->setting_csum.V4Receive.TcpChecksum)
  11.610 -    {
  11.611 -      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
  11.612 -        packet, TcpIpChecksumPacketInfo);
  11.613 -      csum_info->Receive.NdisPacketIpChecksumSucceeded = TRUE;
  11.614 -      csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
  11.615 -    }
  11.616 -    if (psh)
  11.617 -    {
  11.618 -      NdisGetFirstBufferFromPacketSafe(packet, &mdl, &header_va, &buffer_length, &total_length, NormalPagePriority);
  11.619 -      if (pi->tcp_remaining)
  11.620 -        header_va[XN_HDR_SIZE + pi->ip4_header_length + 13] &= ~8;
  11.621 -      else
  11.622 -        header_va[XN_HDR_SIZE + pi->ip4_header_length + 13] |= 8;
  11.623 -    }
  11.624 -    XenNet_SumPacketData(pi, packet, TRUE);
  11.625 -    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
  11.626 -    InsertTailList(rx_packet_list, entry);
  11.627 -    packet_count++;
  11.628 -  }
  11.629 -
  11.630 -done:
  11.631 -  page_buf = pi->first_pb;
  11.632 -  while (page_buf)
  11.633 -  {
  11.634 -    shared_buffer_t *next_pb;
  11.635 -
  11.636 -    next_pb = page_buf->next;
  11.637 -    put_pb_on_freelist(xi, page_buf);
  11.638 -    page_buf = next_pb;
  11.639 -  }
  11.640 -  XenNet_ClearPacketInfo(pi);
  11.641 -  //FUNCTION_EXIT();
  11.642 -  return packet_count;
  11.643 -}
  11.644 -
  11.645 -
  11.646 -/* called at DISPATCH_LEVEL */
  11.647 -/* it's okay for return packet to be called while resume_state != RUNNING as the packet will simply be added back to the freelist, the grants will be fixed later */
  11.648 -VOID
  11.649 -XenNet_ReturnPacket(
  11.650 -  IN NDIS_HANDLE MiniportAdapterContext,
  11.651 -  IN PNDIS_PACKET Packet
  11.652 -  )
  11.653 -{
  11.654 -  struct xennet_info *xi = MiniportAdapterContext;
  11.655 -  PNDIS_BUFFER buffer;
  11.656 -  shared_buffer_t *page_buf = *(shared_buffer_t **)&Packet->MiniportReservedEx[0];
  11.657 -
  11.658 -  //FUNCTION_ENTER();
  11.659 -
  11.660 -  //KdPrint((__DRIVER_NAME "     page_buf = %p\n", page_buf));
  11.661 -
  11.662 -  NdisUnchainBufferAtFront(Packet, &buffer);
  11.663 -  
  11.664 -  while (buffer)
  11.665 -  {
  11.666 -    shared_buffer_t *next_buf;
  11.667 -    ASSERT(page_buf);
  11.668 -    next_buf = page_buf->next;
  11.669 -    if (!page_buf->virtual)
  11.670 -    {
  11.671 -      /* this isn't actually a share_buffer, it is some memory allocated for the header - just free it */
  11.672 -      PUCHAR va;
  11.673 -      UINT len;
  11.674 -      NdisQueryBufferSafe(buffer, &va, &len, NormalPagePriority);
  11.675 -      NdisFreeToNPagedLookasideList(&xi->rx_lookaside_list, va - sizeof(shared_buffer_t));
  11.676 -      NdisFreeBuffer(buffer);
  11.677 -    }
  11.678 -    else
  11.679 -    {
  11.680 -      //KdPrint((__DRIVER_NAME "     returning page_buf %p with id %d\n", page_buf, page_buf->id));
  11.681 -      if (buffer != page_buf->buffer)
  11.682 -        NdisFreeBuffer(buffer);
  11.683 -      put_pb_on_freelist(xi, page_buf);
  11.684 -    }
  11.685 -    NdisUnchainBufferAtFront(Packet, &buffer);
  11.686 -    page_buf = next_buf;
  11.687 -  }
  11.688 -
  11.689 -  put_packet_on_freelist(xi, Packet);
  11.690 -  InterlockedDecrement(&xi->rx_outstanding);
  11.691 -  
  11.692 -  if (!xi->rx_outstanding && xi->rx_shutting_down)
  11.693 -    KeSetEvent(&xi->packet_returned_event, IO_NO_INCREMENT, FALSE);
  11.694 -
  11.695 -#if 0 /* don't do this as it's called an awful lot */
  11.696 -  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
  11.697 -
  11.698 -  XenNet_FillRing(xi);
  11.699 -
  11.700 -  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
  11.701 +#ifdef _GPLPV_NDIS5
  11.702 +#include "xennet5_rx.c"
  11.703 +#else
  11.704 +#include "xennet6_rx.c"
  11.705  #endif
  11.706 -  //FUNCTION_EXIT();
  11.707 -}
  11.708 -
  11.709 -#define MAXIMUM_PACKETS_PER_INDICATE 32
  11.710 -
  11.711 -/* We limit the number of packets per interrupt so that acks get a chance
  11.712 -under high rx load. The DPC is immediately re-scheduled */
  11.713 -#define MAXIMUM_PACKETS_PER_INTERRUPT 32 /* this is calculated before large packet split */
  11.714 -#define MAXIMUM_DATA_PER_INTERRUPT (MAXIMUM_PACKETS_PER_INTERRUPT * 1500) /* help account for large packets */
  11.715 -
  11.716 -// Called at DISPATCH_LEVEL
  11.717 -BOOLEAN
  11.718 -XenNet_RxBufferCheck(struct xennet_info *xi)
  11.719 -{
  11.720 -  RING_IDX cons, prod;
  11.721 -  LIST_ENTRY rx_packet_list;
  11.722 -  LIST_ENTRY rx_header_only_packet_list;
  11.723 -  PLIST_ENTRY entry;
  11.724 -  PNDIS_PACKET packets[MAXIMUM_PACKETS_PER_INDICATE];
  11.725 -  ULONG packet_count = 0;
  11.726 -  ULONG buffer_count = 0;
  11.727 -  ULONG packet_data = 0;
  11.728 -  ULONG interim_packet_data = 0;
  11.729 -  struct netif_extra_info *ei;
  11.730 -  USHORT id;
  11.731 -  int more_to_do = FALSE;
  11.732 -  packet_info_t *pi = &xi->rxpi[KeGetCurrentProcessorNumber() & 0xff];
  11.733 -  shared_buffer_t *page_buf;
  11.734 -  shared_buffer_t *head_buf = NULL;
  11.735 -  shared_buffer_t *tail_buf = NULL;
  11.736 -  shared_buffer_t *last_buf = NULL;
  11.737 -  BOOLEAN extra_info_flag = FALSE;
  11.738 -  BOOLEAN more_data_flag = FALSE;
  11.739 -  PNDIS_BUFFER buffer;
  11.740 -  BOOLEAN dont_set_event;
  11.741 -
  11.742 -  //FUNCTION_ENTER();
  11.743 -
  11.744 -  if (!xi->connected)
  11.745 -    return FALSE; /* a delayed DPC could let this come through... just do nothing */
  11.746 -
  11.747 -  InitializeListHead(&rx_packet_list);
  11.748 -
  11.749 -  /* get all the buffers off the ring as quickly as possible so the lock is held for a minimum amount of time */
  11.750 -
  11.751 -  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
  11.752 -  
  11.753 -  if (xi->rx_shutting_down)
  11.754 -  {
  11.755 -    /* there is a chance that our Dpc had been queued just before the shutdown... */
  11.756 -    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
  11.757 -    return FALSE;
  11.758 -  }
  11.759 -
  11.760 -  if (xi->rx_partial_buf)
  11.761 -  {
  11.762 -    head_buf = xi->rx_partial_buf;
  11.763 -    tail_buf = xi->rx_partial_buf;
  11.764 -    while (tail_buf->next)
  11.765 -      tail_buf = tail_buf->next;
  11.766 -    more_data_flag = xi->rx_partial_more_data_flag;
  11.767 -    extra_info_flag = xi->rx_partial_extra_info_flag;
  11.768 -    xi->rx_partial_buf = NULL;
  11.769 -  }
  11.770 -
  11.771 -  do {
  11.772 -    prod = xi->rx.sring->rsp_prod;
  11.773 -    KeMemoryBarrier(); /* Ensure we see responses up to 'prod'. */
  11.774 -
  11.775 -    for (cons = xi->rx.rsp_cons; cons != prod && packet_count < MAXIMUM_PACKETS_PER_INTERRUPT && packet_data < MAXIMUM_DATA_PER_INTERRUPT; cons++)
  11.776 -    {
  11.777 -      id = (USHORT)(cons & (NET_RX_RING_SIZE - 1));
  11.778 -      page_buf = xi->rx_ring_pbs[id];
  11.779 -      ASSERT(page_buf);
  11.780 -      xi->rx_ring_pbs[id] = NULL;
  11.781 -      xi->rx_id_free++;
  11.782 -      memcpy(&page_buf->rsp, RING_GET_RESPONSE(&xi->rx, cons), max(sizeof(struct netif_rx_response), sizeof(struct netif_extra_info)));
  11.783 -      if (!extra_info_flag)
  11.784 -      {
  11.785 -        if (page_buf->rsp.status <= 0
  11.786 -          || page_buf->rsp.offset + page_buf->rsp.status > PAGE_SIZE)
  11.787 -        {
  11.788 -          KdPrint((__DRIVER_NAME "     Error: rsp offset %d, size %d\n",
  11.789 -            page_buf->rsp.offset, page_buf->rsp.status));
  11.790 -          ASSERT(!extra_info_flag);
  11.791 -          put_pb_on_freelist(xi, page_buf);
  11.792 -          continue;
  11.793 -        }
  11.794 -      }
  11.795 -      
  11.796 -      if (!head_buf)
  11.797 -      {
  11.798 -        head_buf = page_buf;
  11.799 -        tail_buf = page_buf;
  11.800 -      }
  11.801 -      else
  11.802 -      {
  11.803 -        tail_buf->next = page_buf;
  11.804 -        tail_buf = page_buf;
  11.805 -      }
  11.806 -      page_buf->next = NULL;
  11.807 -
  11.808 -      if (extra_info_flag)
  11.809 -      {
  11.810 -        ei = (struct netif_extra_info *)&page_buf->rsp;
  11.811 -        extra_info_flag = ei->flags & XEN_NETIF_EXTRA_FLAG_MORE;
  11.812 -      }
  11.813 -      else
  11.814 -      {
  11.815 -        more_data_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_more_data);
  11.816 -        extra_info_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_extra_info);
  11.817 -        interim_packet_data += page_buf->rsp.status;
  11.818 -      }
  11.819 -      
  11.820 -      if (!extra_info_flag && !more_data_flag)
  11.821 -      {
  11.822 -        last_buf = page_buf;
  11.823 -        packet_count++;
  11.824 -        packet_data += interim_packet_data;
  11.825 -        interim_packet_data = 0;
  11.826 -      }
  11.827 -      buffer_count++;
  11.828 -    }
  11.829 -    xi->rx.rsp_cons = cons;
  11.830 -
  11.831 -    /* Give netback more buffers */
  11.832 -    XenNet_FillRing(xi);
  11.833 -
  11.834 -    if (packet_count >= MAXIMUM_PACKETS_PER_INTERRUPT || packet_data >= MAXIMUM_DATA_PER_INTERRUPT)
  11.835 -      break;
  11.836 -
  11.837 -    more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xi->rx);
  11.838 -    if (!more_to_do)
  11.839 -    {
  11.840 -      xi->rx.sring->rsp_event = xi->rx.rsp_cons + 1;
  11.841 -      KeMemoryBarrier();
  11.842 -      more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xi->rx);
  11.843 -    }
  11.844 -  } while (more_to_do);
  11.845 -  
  11.846 -  /* anything past last_buf belongs to an incomplete packet... */
  11.847 -  if (last_buf && last_buf->next)
  11.848 -  {
  11.849 -    KdPrint((__DRIVER_NAME "     Partial receive\n"));
  11.850 -    xi->rx_partial_buf = last_buf->next;
  11.851 -    xi->rx_partial_more_data_flag = more_data_flag;
  11.852 -    xi->rx_partial_extra_info_flag = extra_info_flag;
  11.853 -    last_buf->next = NULL;
  11.854 -  }
  11.855 -
  11.856 -  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
  11.857 -
  11.858 -  if (packet_count >= MAXIMUM_PACKETS_PER_INTERRUPT || packet_data >= MAXIMUM_DATA_PER_INTERRUPT)
  11.859 -  {
  11.860 -    /* fire again immediately */
  11.861 -    //KdPrint((__DRIVER_NAME "     Dpc Duration Exceeded\n"));
  11.862 -    dpc_limit_hit++;
  11.863 -    /* we want the Dpc on the end of the queue. By definition we are already on the right CPU so we know the Dpc queue will be run immediately */
  11.864 -    KeSetImportanceDpc(&xi->rxtx_dpc, MediumImportance);
  11.865 -    KeInsertQueueDpc(&xi->rxtx_dpc, NULL, NULL);
  11.866 -    /* dont set an event in TX path */
  11.867 -    dont_set_event = TRUE;
  11.868 -  }
  11.869 -  else
  11.870 -  {
  11.871 -    /* make sure the Dpc queue is run immediately next interrupt */
  11.872 -    KeSetImportanceDpc(&xi->rxtx_dpc, HighImportance);
  11.873 -    /* set an event in TX path */
  11.874 -    dont_set_event = FALSE;
  11.875 -  }
  11.876 -
  11.877 -  /* make packets out of the buffers */
  11.878 -  page_buf = head_buf;
  11.879 -  extra_info_flag = FALSE;
  11.880 -  more_data_flag = FALSE;
  11.881 -  while (page_buf)
  11.882 -  {
  11.883 -    shared_buffer_t *next_buf = page_buf->next;
  11.884 -
  11.885 -    page_buf->next = NULL;
  11.886 -    if (extra_info_flag)
  11.887 -    {
  11.888 -      //KdPrint((__DRIVER_NAME "     processing extra info\n"));
  11.889 -      ei = (struct netif_extra_info *)&page_buf->rsp;
  11.890 -      extra_info_flag = ei->flags & XEN_NETIF_EXTRA_FLAG_MORE;
  11.891 -      switch (ei->type)
  11.892 -      {
  11.893 -      case XEN_NETIF_EXTRA_TYPE_GSO:
  11.894 -        switch (ei->u.gso.type)
  11.895 -        {
  11.896 -        case XEN_NETIF_GSO_TYPE_TCPV4:
  11.897 -          pi->mss = ei->u.gso.size;
  11.898 -          //KdPrint((__DRIVER_NAME "     mss = %d\n", pi->mss));
  11.899 -          // TODO - put this assertion somewhere ASSERT(header_len + pi->mss <= PAGE_SIZE); // this limits MTU to PAGE_SIZE - XN_HEADER_LEN
  11.900 -          break;
  11.901 -        default:
  11.902 -          KdPrint((__DRIVER_NAME "     Unknown GSO type (%d) detected\n", ei->u.gso.type));
  11.903 -          break;
  11.904 -        }
  11.905 -        break;
  11.906 -      default:
  11.907 -        KdPrint((__DRIVER_NAME "     Unknown extra info type (%d) detected\n", ei->type));
  11.908 -        break;
  11.909 -      }
  11.910 -      put_pb_on_freelist(xi, page_buf);
  11.911 -    }
  11.912 -    else
  11.913 -    {
  11.914 -      ASSERT(!page_buf->rsp.offset);
  11.915 -      if (!more_data_flag) // handling the packet's 1st buffer
  11.916 -      {
  11.917 -        if (page_buf->rsp.flags & NETRXF_csum_blank)
  11.918 -          pi->csum_blank = TRUE;
  11.919 -        if (page_buf->rsp.flags & NETRXF_data_validated)
  11.920 -          pi->data_validated = TRUE;
  11.921 -      }
  11.922 -      buffer = page_buf->buffer;
  11.923 -      NdisAdjustBufferLength(buffer, page_buf->rsp.status);
  11.924 -      //KdPrint((__DRIVER_NAME "     buffer = %p, pb = %p\n", buffer, page_buf));
  11.925 -      if (pi->first_pb)
  11.926 -      {
  11.927 -        ASSERT(pi->curr_pb);
  11.928 -        //KdPrint((__DRIVER_NAME "     additional buffer\n"));
  11.929 -        pi->curr_pb->next = page_buf;
  11.930 -        pi->curr_pb = page_buf;
  11.931 -        ASSERT(pi->curr_buffer);
  11.932 -        NDIS_BUFFER_LINKAGE(pi->curr_buffer) = buffer;
  11.933 -        pi->curr_buffer = buffer;
  11.934 -      }
  11.935 -      else
  11.936 -      {
  11.937 -        pi->first_pb = page_buf;
  11.938 -        pi->curr_pb = page_buf;
  11.939 -        pi->first_buffer = buffer;
  11.940 -        pi->curr_buffer = buffer;
  11.941 -      }
  11.942 -      pi->mdl_count++;
  11.943 -      extra_info_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_extra_info);
  11.944 -      more_data_flag = (BOOLEAN)(page_buf->rsp.flags & NETRXF_more_data);
  11.945 -      pi->total_length = pi->total_length + page_buf->rsp.status;
  11.946 -    }
  11.947 -
  11.948 -    /* Packet done, add it to the list */
  11.949 -    if (!more_data_flag && !extra_info_flag)
  11.950 -    {
  11.951 -      pi->curr_pb = pi->first_pb;
  11.952 -      pi->curr_buffer = pi->first_buffer;
  11.953 -      XenNet_MakePackets(xi, &rx_packet_list, pi);
  11.954 -    }
  11.955 -
  11.956 -    page_buf = next_buf;
  11.957 -  }
  11.958 -  ASSERT(!more_data_flag && !extra_info_flag);
  11.959 -      
  11.960 -  xi->stat_rx_ok += packet_count;
  11.961 -
  11.962 -  /* indicate packets to NDIS */
  11.963 -  entry = RemoveHeadList(&rx_packet_list);
  11.964 -  InitializeListHead(&rx_header_only_packet_list);
  11.965 -  packet_count = 0;
  11.966 -
  11.967 -  while (entry != &rx_packet_list) {
  11.968 -    PNDIS_PACKET packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
  11.969 -    NDIS_STATUS status;
  11.970 -    ASSERT(*(shared_buffer_t **)&packet->MiniportReservedEx[0]);
  11.971 -    status = NDIS_GET_PACKET_STATUS(packet);
  11.972 -    if (status == NDIS_STATUS_RESOURCES)
  11.973 -      InsertTailList(&rx_header_only_packet_list, entry);
  11.974 -    packets[packet_count++] = packet;
  11.975 -    InterlockedIncrement(&xi->rx_outstanding);
  11.976 -    entry = RemoveHeadList(&rx_packet_list);
  11.977 -    /* if we indicate a packet with NDIS_STATUS_RESOURCES  then any following packet can't be NDIS_STATUS_SUCCESS */
  11.978 -    if (packet_count == MAXIMUM_PACKETS_PER_INDICATE || entry == &rx_packet_list
  11.979 -        || (NDIS_GET_PACKET_STATUS(CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)])) == NDIS_STATUS_SUCCESS
  11.980 -            && status == NDIS_STATUS_RESOURCES))
  11.981 -    {
  11.982 -      NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
  11.983 -      packet_count = 0;
  11.984 -    }
  11.985 -  }
  11.986 -  /* now return the packets for which we indicated NDIS_STATUS_RESOURCES */
  11.987 -  entry = RemoveHeadList(&rx_header_only_packet_list);
  11.988 -  while (entry != &rx_header_only_packet_list) {
  11.989 -    PNDIS_PACKET packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
  11.990 -    entry = RemoveHeadList(&rx_header_only_packet_list);
  11.991 -    InterlockedIncrement(&resource_packets);
  11.992 -    XenNet_ReturnPacket(xi, packet);
  11.993 -  }
  11.994 -  return dont_set_event;
  11.995 -  //FUNCTION_EXIT();
  11.996 -}
  11.997 -
  11.998 -/*
  11.999 -   Free all Rx buffers (on halt, for example) 
 11.1000 -   The ring must be stopped at this point.
 11.1001 -*/
 11.1002 -
 11.1003 -static VOID
 11.1004 -XenNet_PurgeRing(struct xennet_info *xi)
 11.1005 -{
 11.1006 -  int i;
 11.1007 -  for (i = 0; i < NET_RX_RING_SIZE; i++)
 11.1008 -  {
 11.1009 -    if (xi->rx_ring_pbs[i] != NULL)
 11.1010 -    {
 11.1011 -      put_pb_on_freelist(xi, xi->rx_ring_pbs[i]);
 11.1012 -      xi->rx_ring_pbs[i] = NULL;
 11.1013 -    }
 11.1014 -  }
 11.1015 -}
 11.1016 -
 11.1017 -static VOID
 11.1018 -XenNet_BufferFree(struct xennet_info *xi)
 11.1019 -{
 11.1020 -  shared_buffer_t *pb;
 11.1021 -
 11.1022 -  XenNet_PurgeRing(xi);
 11.1023 -
 11.1024 -  while ((pb = get_pb_from_freelist(xi)) != NULL)
 11.1025 -  {
 11.1026 -    NdisFreeBuffer(pb->buffer);
 11.1027 -    xi->vectors.GntTbl_EndAccess(xi->vectors.context,
 11.1028 -        pb->gref, FALSE, (ULONG)'XNRX');
 11.1029 -    NdisFreeMemory(pb->virtual, PAGE_SIZE, 0);
 11.1030 -    NdisFreeMemory(pb, sizeof(shared_buffer_t), 0);
 11.1031 -  }
 11.1032 -}
 11.1033 -
 11.1034 -VOID
 11.1035 -XenNet_RxResumeStart(xennet_info_t *xi)
 11.1036 -{
 11.1037 -  KIRQL old_irql;
 11.1038 -
 11.1039 -  FUNCTION_ENTER();
 11.1040 -
 11.1041 -  KeAcquireSpinLock(&xi->rx_lock, &old_irql);
 11.1042 -  XenNet_PurgeRing(xi);
 11.1043 -  KeReleaseSpinLock(&xi->rx_lock, old_irql);
 11.1044 -  
 11.1045 -  FUNCTION_EXIT();
 11.1046 -}
 11.1047 -
 11.1048 -VOID
 11.1049 -XenNet_BufferAlloc(xennet_info_t *xi)
 11.1050 -{
 11.1051 -  //NDIS_STATUS status;
 11.1052 -  int i;
 11.1053 -  
 11.1054 -  xi->rx_id_free = NET_RX_RING_SIZE;
 11.1055 -  xi->rx_outstanding = 0;
 11.1056 -
 11.1057 -  for (i = 0; i < NET_RX_RING_SIZE; i++)
 11.1058 -  {
 11.1059 -    xi->rx_ring_pbs[i] = NULL;
 11.1060 -  }
 11.1061 -}
 11.1062 -
 11.1063 -VOID
 11.1064 -XenNet_RxResumeEnd(xennet_info_t *xi)
 11.1065 -{
 11.1066 -  KIRQL old_irql;
 11.1067 -
 11.1068 -  FUNCTION_ENTER();
 11.1069 -
 11.1070 -  KeAcquireSpinLock(&xi->rx_lock, &old_irql);
 11.1071 -  //XenNet_BufferAlloc(xi);
 11.1072 -  XenNet_FillRing(xi);
 11.1073 -  KeReleaseSpinLock(&xi->rx_lock, old_irql);
 11.1074 -  
 11.1075 -  FUNCTION_EXIT();
 11.1076 -}
 11.1077 -
 11.1078 -BOOLEAN
 11.1079 -XenNet_RxInit(xennet_info_t *xi)
 11.1080 -{
 11.1081 -  NDIS_STATUS status;
 11.1082 -
 11.1083 -  FUNCTION_ENTER();
 11.1084 -
 11.1085 -  xi->rx_shutting_down = FALSE;
 11.1086 -  KeInitializeSpinLock(&xi->rx_lock);
 11.1087 -  KeInitializeEvent(&xi->packet_returned_event, SynchronizationEvent, FALSE);
 11.1088 -  KeInitializeTimer(&xi->rx_timer);
 11.1089 -  status = NdisAllocateMemoryWithTag((PVOID)&xi->rxpi, sizeof(packet_info_t) * NdisSystemProcessorCount(), XENNET_POOL_TAG);
 11.1090 -  if (status != NDIS_STATUS_SUCCESS)
 11.1091 -  {
 11.1092 -    KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
 11.1093 -    return FALSE;
 11.1094 -  }
 11.1095 -  NdisZeroMemory(xi->rxpi, sizeof(packet_info_t) * NdisSystemProcessorCount());
 11.1096 -
 11.1097 -  stack_new(&xi->rx_pb_stack, NET_RX_RING_SIZE * 4);
 11.1098 -
 11.1099 -  XenNet_BufferAlloc(xi);
 11.1100 -  
 11.1101 -  NdisAllocatePacketPool(&status, &xi->rx_packet_pool, NET_RX_RING_SIZE * 4,
 11.1102 -    PROTOCOL_RESERVED_SIZE_IN_PACKET);
 11.1103 -  if (status != NDIS_STATUS_SUCCESS)
 11.1104 -  {
 11.1105 -    KdPrint(("NdisAllocatePacketPool failed with 0x%x\n", status));
 11.1106 -    return FALSE;
 11.1107 -  }
 11.1108 -  stack_new(&xi->rx_packet_stack, NET_RX_RING_SIZE * 4);
 11.1109 -
 11.1110 -  NdisInitializeNPagedLookasideList(&xi->rx_lookaside_list, NULL, NULL, 0,
 11.1111 -    MAX_ETH_HEADER_LENGTH + MAX_LOOKAHEAD_LENGTH + sizeof(shared_buffer_t), XENNET_POOL_TAG, 0);
 11.1112 -  
 11.1113 -  XenNet_FillRing(xi);
 11.1114 -
 11.1115 -  FUNCTION_EXIT();
 11.1116 -
 11.1117 -  return TRUE;
 11.1118 -}
 11.1119 -
 11.1120 -BOOLEAN
 11.1121 -XenNet_RxShutdown(xennet_info_t *xi)
 11.1122 -{
 11.1123 -  KIRQL old_irql;
 11.1124 -  PNDIS_PACKET packet;
 11.1125 -
 11.1126 -  FUNCTION_ENTER();
 11.1127 -
 11.1128 -  KeAcquireSpinLock(&xi->rx_lock, &old_irql);
 11.1129 -  xi->rx_shutting_down = TRUE;
 11.1130 -  KeReleaseSpinLock(&xi->rx_lock, old_irql);
 11.1131 -
 11.1132 -  if (xi->config_rx_interrupt_moderation)
 11.1133 -  {
 11.1134 -    KeCancelTimer(&xi->rx_timer);
 11.1135 -  }
 11.1136 -
 11.1137 -#if (NTDDI_VERSION >= NTDDI_WINXP)
 11.1138 -  KeFlushQueuedDpcs();
 11.1139 -#endif
 11.1140 -
 11.1141 -  while (xi->rx_outstanding)
 11.1142 -  {
 11.1143 -    KdPrint((__DRIVER_NAME "     Waiting for all packets to be returned\n"));
 11.1144 -    KeWaitForSingleObject(&xi->packet_returned_event, Executive, KernelMode, FALSE, NULL);
 11.1145 -  }
 11.1146 -
 11.1147 -  //KeAcquireSpinLock(&xi->rx_lock, &old_irql);
 11.1148 -
 11.1149 -  NdisFreeMemory(xi->rxpi, sizeof(packet_info_t) * NdisSystemProcessorCount(), 0);
 11.1150 -
 11.1151 -  XenNet_BufferFree(xi);
 11.1152 -
 11.1153 -  /* this works because get_packet_from_freelist won't allocate new packets when rx_shutting_down */
 11.1154 -  while ((packet = get_packet_from_freelist(xi)) != NULL)
 11.1155 -    NdisFreePacket(packet);
 11.1156 -  stack_delete(xi->rx_packet_stack, NULL, NULL);
 11.1157 -  NdisFreePacketPool(xi->rx_packet_pool);
 11.1158 -
 11.1159 -  NdisDeleteNPagedLookasideList(&xi->rx_lookaside_list);
 11.1160 -
 11.1161 -  stack_delete(xi->rx_pb_stack, NULL, NULL);
 11.1162 -  //KeReleaseSpinLock(&xi->rx_lock, old_irql);
 11.1163 -
 11.1164 -  FUNCTION_EXIT();
 11.1165 -
 11.1166 -  return TRUE;
 11.1167 -}
    12.1 --- a/xennet/xennet_tx.c	Sat Apr 30 00:24:01 2011 +1000
    12.2 +++ b/xennet/xennet_tx.c	Sat Apr 30 10:57:23 2011 +1000
    12.3 @@ -1,715 +1,5 @@
    12.4 -/*
    12.5 -PV Net Driver for Windows Xen HVM Domains
    12.6 -Copyright (C) 2007 James Harper
    12.7 -Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
    12.8 -
    12.9 -This program is free software; you can redistribute it and/or
   12.10 -modify it under the terms of the GNU General Public License
   12.11 -as published by the Free Software Foundation; either version 2
   12.12 -of the License, or (at your option) any later version.
   12.13 -
   12.14 -This program is distributed in the hope that it will be useful,
   12.15 -but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.16 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.17 -GNU General Public License for more details.
   12.18 -
   12.19 -You should have received a copy of the GNU General Public License
   12.20 -along with this program; if not, write to the Free Software
   12.21 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   12.22 -*/
   12.23 -
   12.24 -#include "xennet.h"
   12.25 -
   12.26 -static USHORT
   12.27 -get_id_from_freelist(struct xennet_info *xi)
   12.28 -{
   12.29 -  ASSERT(xi->tx_id_free);
   12.30 -  xi->tx_id_free--;
   12.31 -
   12.32 -  return xi->tx_id_list[xi->tx_id_free];
   12.33 -}
   12.34 -
   12.35 -static VOID
   12.36 -put_id_on_freelist(struct xennet_info *xi, USHORT id)
   12.37 -{
   12.38 -  xi->tx_id_list[xi->tx_id_free] = id;
   12.39 -  xi->tx_id_free++;
   12.40 -}
   12.41 -
   12.42 -#define SWAP_USHORT(x) (USHORT)((((x & 0xFF) << 8)|((x >> 8) & 0xFF)))
   12.43 -
   12.44 -static __forceinline struct netif_tx_request *
   12.45 -XenNet_PutCbOnRing(struct xennet_info *xi, PVOID coalesce_buf, ULONG length, grant_ref_t gref)
   12.46 -{
   12.47 -  struct netif_tx_request *tx;
   12.48 -  tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   12.49 -  xi->tx.req_prod_pvt++;
   12.50 -  xi->tx_ring_free--;
   12.51 -  tx->id = get_id_from_freelist(xi);
   12.52 -  ASSERT(xi->tx_shadows[tx->id].gref == INVALID_GRANT_REF);
   12.53 -  ASSERT(!xi->tx_shadows[tx->id].cb);
   12.54 -  xi->tx_shadows[tx->id].cb = coalesce_buf;
   12.55 -  tx->gref = xi->vectors.GntTbl_GrantAccess(xi->vectors.context, 0, (ULONG)(MmGetPhysicalAddress(coalesce_buf).QuadPart >> PAGE_SHIFT), FALSE, gref, (ULONG)'XNTX');
   12.56 -  xi->tx_shadows[tx->id].gref = tx->gref;
   12.57 -  tx->offset = 0;
   12.58 -  tx->size = (USHORT)length;
   12.59 -  ASSERT(tx->offset + tx->size <= PAGE_SIZE);
   12.60 -  ASSERT(tx->size);
   12.61 -  return tx;
   12.62 -}
   12.63 -  
   12.64 -/* Called at DISPATCH_LEVEL with tx_lock held */
   12.65 -/*
   12.66 - * Send one NDIS_PACKET. This may involve multiple entries on TX ring.
   12.67 - */
   12.68 -static BOOLEAN
   12.69 -XenNet_HWSendPacket(struct xennet_info *xi, PNDIS_PACKET packet)
   12.70 -{
   12.71 -  struct netif_tx_request *tx0 = NULL;
   12.72 -  struct netif_tx_request *txN = NULL;
   12.73 -  struct netif_extra_info *ei = NULL;
   12.74 -  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   12.75 -  ULONG mss = 0;
   12.76 -  uint16_t flags = NETTXF_more_data;
   12.77 -  packet_info_t pi;
   12.78 -  BOOLEAN ndis_lso = FALSE;
   12.79 -  BOOLEAN xen_gso = FALSE;
   12.80 -  ULONG remaining;
   12.81 -  ULONG parse_result;
   12.82 -  ULONG frags = 0;
   12.83 -  BOOLEAN coalesce_required = FALSE;
   12.84 -  PVOID coalesce_buf;
   12.85 -  ULONG coalesce_remaining = 0;
   12.86 -  grant_ref_t gref;
   12.87 -  ULONG tx_length = 0;
   12.88 -  
   12.89 -  //FUNCTION_ENTER();
   12.90 -
   12.91 -  gref = xi->vectors.GntTbl_GetRef(xi->vectors.context, (ULONG)'XNTX');
   12.92 -  if (gref == INVALID_GRANT_REF)
   12.93 -  {
   12.94 -    KdPrint((__DRIVER_NAME "     out of grefs\n"));
   12.95 -    return FALSE;
   12.96 -  }
   12.97 -  coalesce_buf = NdisAllocateFromNPagedLookasideList(&xi->tx_lookaside_list);
   12.98 -  if (!coalesce_buf)
   12.99 -  {
  12.100 -    xi->vectors.GntTbl_PutRef(xi->vectors.context, gref, (ULONG)'XNTX');
  12.101 -    KdPrint((__DRIVER_NAME "     out of memory\n"));
  12.102 -    return FALSE;
  12.103 -  }
  12.104 -  XenNet_ClearPacketInfo(&pi);
  12.105 -  NdisQueryPacket(packet, NULL, (PUINT)&pi.mdl_count, &pi.first_buffer, (PUINT)&pi.total_length);
  12.106 -  
  12.107 -  pi.curr_mdl_offset = 0;
  12.108 -  pi.curr_buffer = pi.first_buffer;
  12.109 -  remaining = min(pi.total_length, PAGE_SIZE);
  12.110 -  while (remaining) /* this much gets put in the header */
  12.111 -  {
  12.112 -    ULONG length = XenNet_QueryData(&pi, remaining);
  12.113 -    remaining -= length;
  12.114 -    XenNet_EatData(&pi, length);
  12.115 -  }
  12.116 -  frags++;
  12.117 -  if (pi.total_length > PAGE_SIZE) /* these are the frags we care about */
  12.118 -  {
  12.119 -    remaining = pi.total_length - PAGE_SIZE;
  12.120 -    while (remaining)
  12.121 -    {
  12.122 -      ULONG length = XenNet_QueryData(&pi, PAGE_SIZE);
  12.123 -      if (length != 0)
  12.124 -      {
  12.125 -        frags++;
  12.126 -        if (frags > LINUX_MAX_SG_ELEMENTS)
  12.127 -          break; /* worst case there could be hundreds of fragments - leave the loop now */
  12.128 -      }
  12.129 -      remaining -= length;
  12.130 -      XenNet_EatData(&pi, length);
  12.131 -    }
  12.132 -  }
  12.133 -  if (frags > LINUX_MAX_SG_ELEMENTS)
  12.134 -  {
  12.135 -    frags = LINUX_MAX_SG_ELEMENTS;
  12.136 -    coalesce_required = TRUE;
  12.137 -  }
  12.138 -
  12.139 -  /* if we have enough space on the ring then we have enough id's so no need to check for that */
  12.140 -  if (xi->tx_ring_free < frags + 1)
  12.141 -  {
  12.142 -    xi->vectors.GntTbl_PutRef(xi->vectors.context, gref, (ULONG)'XNTX');
  12.143 -    NdisFreeToNPagedLookasideList(&xi->tx_lookaside_list, coalesce_buf);
  12.144 -    //KdPrint((__DRIVER_NAME "     Full on send - ring full\n"));
  12.145 -    return FALSE;
  12.146 -  }
  12.147 -  
  12.148 -  parse_result = XenNet_ParsePacketHeader(&pi, coalesce_buf, PAGE_SIZE);
  12.149 -  remaining = pi.total_length - pi.header_length;
  12.150 -
  12.151 -  if (NDIS_GET_PACKET_PROTOCOL_TYPE(packet) == NDIS_PROTOCOL_ID_TCP_IP)
  12.152 -  {
  12.153 -    csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
  12.154 -      packet, TcpIpChecksumPacketInfo);
  12.155 -    if (csum_info->Transmit.NdisPacketChecksumV4)
  12.156 -    {
  12.157 -      if (csum_info->Transmit.NdisPacketIpChecksum && !xi->setting_csum.V4Transmit.IpChecksum)
  12.158 -      {
  12.159 -        KdPrint((__DRIVER_NAME "     IpChecksum not enabled\n"));
  12.160 -        //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
  12.161 -        //return TRUE;
  12.162 -      }
  12.163 -      if (csum_info->Transmit.NdisPacketTcpChecksum)
  12.164 -      {
  12.165 -        if (xi->setting_csum.V4Transmit.TcpChecksum)
  12.166 -        {
  12.167 -          flags |= NETTXF_csum_blank | NETTXF_data_validated;
  12.168 -        }
  12.169 -        else
  12.170 -        {
  12.171 -          KdPrint((__DRIVER_NAME "     TcpChecksum not enabled\n"));
  12.172 -          //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
  12.173 -          //return TRUE;
  12.174 -        }
  12.175 -      }
  12.176 -      else if (csum_info->Transmit.NdisPacketUdpChecksum)
  12.177 -      {
  12.178 -        if (xi->setting_csum.V4Transmit.UdpChecksum)
  12.179 -        {
  12.180 -          flags |= NETTXF_csum_blank | NETTXF_data_validated;
  12.181 -        }
  12.182 -        else
  12.183 -        {
  12.184 -          KdPrint((__DRIVER_NAME "     UdpChecksum not enabled\n"));
  12.185 -          //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
  12.186 -          //return TRUE;
  12.187 -        }
  12.188 -      }
  12.189 -    }
  12.190 -    else if (csum_info->Transmit.NdisPacketChecksumV6)
  12.191 -    {
  12.192 -      KdPrint((__DRIVER_NAME "     NdisPacketChecksumV6 not supported\n"));
  12.193 -      //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
  12.194 -      //return TRUE;
  12.195 -    }
  12.196 -  }
  12.197 -  
  12.198 -  mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
  12.199 -
  12.200 -  if (mss && parse_result == PARSE_OK)
  12.201 -  {
  12.202 -    if (NDIS_GET_PACKET_PROTOCOL_TYPE(packet) != NDIS_PROTOCOL_ID_TCP_IP)
  12.203 -    {
  12.204 -      KdPrint((__DRIVER_NAME "     mss specified when packet is not NDIS_PROTOCOL_ID_TCP_IP\n"));
  12.205 -    }
  12.206 -    ndis_lso = TRUE;
  12.207 -    if (mss > xi->setting_max_offload)
  12.208 -    {
  12.209 -      KdPrint((__DRIVER_NAME "     Requested MSS (%d) larger than allowed MSS (%d)\n", mss, xi->setting_max_offload));
  12.210 -      //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
  12.211 -      //FUNCTION_EXIT();
  12.212 -      return TRUE;
  12.213 -    }
  12.214 -  }
  12.215 -
  12.216 -  if (ndis_lso)
  12.217 -  {    
  12.218 -    flags |= NETTXF_csum_blank | NETTXF_data_validated; /* these may be implied but not specified when lso is used*/
  12.219 -    if (pi.tcp_length >= mss)
  12.220 -    {
  12.221 -      flags |= NETTXF_extra_info;
  12.222 -      xen_gso = TRUE;
  12.223 -    }
  12.224 -    else
  12.225 -    {
  12.226 -      KdPrint((__DRIVER_NAME "     large send specified when tcp_length < mss\n"));
  12.227 -    }
  12.228 -  }
  12.229 -
  12.230 -/*
  12.231 -* See io/netif.h. Must put (A) 1st request, then (B) optional extra_info, then
  12.232 -* (C) rest of requests on the ring. Only (A) has csum flags.
  12.233 -*/
  12.234 -
  12.235 -  /* (A) */
  12.236 -  tx0 = XenNet_PutCbOnRing(xi, coalesce_buf, pi.header_length, gref);
  12.237 -  ASSERT(tx0); /* this will never happen */
  12.238 -  tx0->flags = flags;
  12.239 -  tx_length += pi.header_length;
  12.240 -
  12.241 -  /* even though we haven't reported that we are capable of it, LSO demands that we calculate the IP Header checksum */
  12.242 -  if (ndis_lso)
  12.243 -  {
  12.244 -    XenNet_SumIpHeader(coalesce_buf, pi.ip4_header_length);
  12.245 -  }
  12.246 -  txN = tx0;
  12.247 -
  12.248 -  /* (B) */
  12.249 -  if (xen_gso)
  12.250 -  {
  12.251 -    ASSERT(flags & NETTXF_extra_info);
  12.252 -    ei = (struct netif_extra_info *)RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
  12.253 -    //KdPrint((__DRIVER_NAME "     pos = %d\n", xi->tx.req_prod_pvt));
  12.254 -    xi->tx.req_prod_pvt++;
  12.255 -    xi->tx_ring_free--;
  12.256 -    ei->type = XEN_NETIF_EXTRA_TYPE_GSO;
  12.257 -    ei->flags = 0;
  12.258 -    ei->u.gso.size = (USHORT)mss;
  12.259 -    ei->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
  12.260 -    ei->u.gso.pad = 0;
  12.261 -    ei->u.gso.features = 0;
  12.262 -  }
  12.263 -
  12.264 -  ASSERT(xi->config_sg || !remaining);
  12.265 -  
  12.266 -  /* (C) - only if data is remaining */
  12.267 -  coalesce_buf = NULL;
  12.268 -  while (remaining > 0)
  12.269 -  {
  12.270 -    ULONG length;
  12.271 -    PFN_NUMBER pfn;
  12.272 -    
  12.273 -    ASSERT(pi.curr_buffer);
  12.274 -    if (coalesce_required)
  12.275 -    {
  12.276 -      PVOID va;
  12.277 -      if (!coalesce_buf)
  12.278 -      {
  12.279 -        gref = xi->vectors.GntTbl_GetRef(xi->vectors.context, (ULONG)'XNTX');
  12.280 -        if (gref == INVALID_GRANT_REF)
  12.281 -        {
  12.282 -          KdPrint((__DRIVER_NAME "     out of grefs - partial send\n"));
  12.283 -          break;
  12.284 -        }
  12.285 -        coalesce_buf = NdisAllocateFromNPagedLookasideList(&xi->tx_lookaside_list);
  12.286 -        if (!coalesce_buf)
  12.287 -        {
  12.288 -          xi->vectors.GntTbl_PutRef(xi->vectors.context, gref, (ULONG)'XNTX');
  12.289 -          KdPrint((__DRIVER_NAME "     out of memory - partial send\n"));
  12.290 -          break;
  12.291 -        }
  12.292 -        coalesce_remaining = min(PAGE_SIZE, remaining);
  12.293 -      }
  12.294 -      length = XenNet_QueryData(&pi, coalesce_remaining);
  12.295 -      va = NdisBufferVirtualAddressSafe(pi.curr_buffer, LowPagePriority);
  12.296 -      if (!va)
  12.297 -      {
  12.298 -        KdPrint((__DRIVER_NAME "     failed to map buffer va - partial send\n"));
  12.299 -        coalesce_remaining = 0;
  12.300 -        remaining -= min(PAGE_SIZE, remaining);
  12.301 -        NdisFreeToNPagedLookasideList(&xi->tx_lookaside_list, coalesce_buf);
  12.302 -      }
  12.303 -      else
  12.304 -      {
  12.305 -        memcpy((PUCHAR)coalesce_buf + min(PAGE_SIZE, remaining) - coalesce_remaining, (PUCHAR)va + pi.curr_mdl_offset, length);
  12.306 -        coalesce_remaining -= length;
  12.307 -      }
  12.308 -    }
  12.309 -    else
  12.310 -    {
  12.311 -      length = XenNet_QueryData(&pi, PAGE_SIZE);
  12.312 -    }
  12.313 -    if (!length || coalesce_remaining) /* sometimes there are zero length buffers... */
  12.314 -    {
  12.315 -      XenNet_EatData(&pi, length); /* do this so we actually move to the next buffer */
  12.316 -      continue;
  12.317 -    }
  12.318 -
  12.319 -    if (coalesce_buf)
  12.320 -    {
  12.321 -      if (remaining)
  12.322 -      {
  12.323 -        txN = XenNet_PutCbOnRing(xi, coalesce_buf, min(PAGE_SIZE, remaining), gref);
  12.324 -        ASSERT(txN);
  12.325 -        coalesce_buf = NULL;
  12.326 -        remaining -= min(PAGE_SIZE, remaining);
  12.327 -        tx_length += min(PAGE_SIZE, remaining);
  12.328 -      }
  12.329 -    }
  12.330 -    else
  12.331 -    {
  12.332 -      ULONG offset;
  12.333 -      
  12.334 -      gref = xi->vectors.GntTbl_GetRef(xi->vectors.context, (ULONG)'XNTX');
  12.335 -      if (gref == INVALID_GRANT_REF)
  12.336 -      {
  12.337 -        KdPrint((__DRIVER_NAME "     out of grefs - partial send\n"));
  12.338 -        break;
  12.339 -      }
  12.340 -      txN = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
  12.341 -      xi->tx.req_prod_pvt++;
  12.342 -      xi->tx_ring_free--;
  12.343 -      txN->id = get_id_from_freelist(xi);
  12.344 -      ASSERT(!xi->tx_shadows[txN->id].cb);
  12.345 -      offset = MmGetMdlByteOffset(pi.curr_buffer) + pi.curr_mdl_offset;
  12.346 -      pfn = MmGetMdlPfnArray(pi.curr_buffer)[offset >> PAGE_SHIFT];
  12.347 -      txN->offset = (USHORT)offset & (PAGE_SIZE - 1);
  12.348 -      txN->gref = xi->vectors.GntTbl_GrantAccess(xi->vectors.context, 0, (ULONG)pfn, FALSE, gref, (ULONG)'XNTX');
  12.349 -      ASSERT(xi->tx_shadows[txN->id].gref == INVALID_GRANT_REF);
  12.350 -      xi->tx_shadows[txN->id].gref = txN->gref;
  12.351 -      //ASSERT(sg->Elements[sg_element].Length > sg_offset);
  12.352 -      txN->size = (USHORT)length;
  12.353 -      ASSERT(txN->offset + txN->size <= PAGE_SIZE);
  12.354 -      ASSERT(txN->size);
  12.355 -      ASSERT(txN->gref != INVALID_GRANT_REF);
  12.356 -      remaining -= length;
  12.357 -      tx_length += length;
  12.358 -    }
  12.359 -    tx0->size = tx0->size + txN->size;
  12.360 -    txN->flags = NETTXF_more_data;
  12.361 -    XenNet_EatData(&pi, length);
  12.362 -  }
  12.363 -  txN->flags &= ~NETTXF_more_data;
  12.364 -  ASSERT(tx0->size == pi.total_length);
  12.365 -  ASSERT(!xi->tx_shadows[txN->id].packet);
  12.366 -  xi->tx_shadows[txN->id].packet = packet;
  12.367 -
  12.368 -  if (ndis_lso)
  12.369 -  {
  12.370 -    //KdPrint((__DRIVER_NAME "     TcpLargeSendPacketInfo = %d\n", pi.tcp_length));
  12.371 -    NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo) = UlongToPtr(tx_length - MAX_ETH_HEADER_LENGTH - pi.ip4_header_length - pi.tcp_header_length);
  12.372 -  }
  12.373 -
  12.374 -  xi->stat_tx_ok++;
  12.375 -
  12.376 -  //NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
  12.377 -  //FUNCTION_EXIT();
  12.378 -  xi->tx_outstanding++;
  12.379 -  return TRUE;
  12.380 -}
  12.381 -
  12.382 -/* Called at DISPATCH_LEVEL with tx_lock held */
  12.383 -
  12.384 -static VOID
  12.385 -XenNet_SendQueuedPackets(struct xennet_info *xi)
  12.386 -{
  12.387 -  PLIST_ENTRY entry;
  12.388 -  PNDIS_PACKET packet;
  12.389 -  int notify;
  12.390 -
  12.391 -  //FUNCTION_ENTER();
  12.392 -
  12.393 -  if (xi->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
  12.394 -    return;
  12.395 -
  12.396 -  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
  12.397 -  /* if empty, the above returns head*, not NULL */
  12.398 -  while (entry != &xi->tx_waiting_pkt_list)
  12.399 -  {
  12.400 -    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
  12.401 -    if (!XenNet_HWSendPacket(xi, packet))
  12.402 -    {
  12.403 -      //KdPrint((__DRIVER_NAME "     No room for packet\n"));
  12.404 -      InsertHeadList(&xi->tx_waiting_pkt_list, entry);
  12.405 -      break;
  12.406 -    }
  12.407 -    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
  12.408 -  }
  12.409 -
  12.410 -  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->tx, notify);
  12.411 -  if (notify)
  12.412 -  {
  12.413 -    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->event_channel);
  12.414 -  }
  12.415 -  //FUNCTION_EXIT();
  12.416 -}
  12.417 -
  12.418 -//ULONG packets_outstanding = 0;
  12.419 -// Called at DISPATCH_LEVEL
  12.420 -VOID
  12.421 -XenNet_TxBufferGC(struct xennet_info *xi, BOOLEAN dont_set_event)
  12.422 -{
  12.423 -  RING_IDX cons, prod;
  12.424 -  PNDIS_PACKET head = NULL, tail = NULL;
  12.425 -  PNDIS_PACKET packet;
  12.426 -  ULONG tx_packets = 0;
  12.427 -
  12.428 -  //FUNCTION_ENTER();
  12.429 -
  12.430 -  if (!xi->connected)
  12.431 -    return; /* a delayed DPC could let this come through... just do nothing */
  12.432 -  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  12.433 -
  12.434 -  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
  12.435 -
  12.436 -  if (xi->tx_shutting_down && !xi->tx_outstanding)
  12.437 -  {
  12.438 -    /* there is a chance that our Dpc had been queued just before the shutdown... */
  12.439 -    KeSetEvent(&xi->tx_idle_event, IO_NO_INCREMENT, FALSE);
  12.440 -    KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
  12.441 -    return;
  12.442 -  }
  12.443 -
  12.444 -  do {
  12.445 -    prod = xi->tx.sring->rsp_prod;
  12.446 -    KeMemoryBarrier(); /* Ensure we see responses up to 'rsp_prod'. */
  12.447 -
  12.448 -    for (cons = xi->tx.rsp_cons; cons != prod; cons++)
  12.449 -    {
  12.450 -      struct netif_tx_response *txrsp;
  12.451 -      tx_shadow_t *shadow;
  12.452 -      
  12.453 -      txrsp = RING_GET_RESPONSE(&xi->tx, cons);
  12.454 -      
  12.455 -      xi->tx_ring_free++;
  12.456 -      
  12.457 -      if (txrsp->status == NETIF_RSP_NULL)
  12.458 -      {
  12.459 -        continue;
  12.460 -      }
  12.461 -
  12.462 -      shadow = &xi->tx_shadows[txrsp->id];
  12.463 -      if (shadow->cb)
  12.464 -      {
  12.465 -        NdisFreeToNPagedLookasideList(&xi->tx_lookaside_list, shadow->cb);
  12.466 -        shadow->cb = NULL;
  12.467 -      }
  12.468 -      
  12.469 -      if (shadow->gref != INVALID_GRANT_REF)
  12.470 -      {
  12.471 -        xi->vectors.GntTbl_EndAccess(xi->vectors.context,
  12.472 -          shadow->gref, FALSE, (ULONG)'XNTX');
  12.473 -        shadow->gref = INVALID_GRANT_REF;
  12.474 -      }
  12.475 -      
  12.476 -      if (shadow->packet)
  12.477 -      {
  12.478 -        packet = shadow->packet;
  12.479 -        *(PNDIS_PACKET *)&packet->MiniportReservedEx[0] = NULL;
  12.480 -        if (head)
  12.481 -          *(PNDIS_PACKET *)&tail->MiniportReservedEx[0] = packet;
  12.482 -        else
  12.483 -          head = packet;
  12.484 -        tail = packet;
  12.485 -        shadow->packet = NULL;
  12.486 -      }
  12.487 -      put_id_on_freelist(xi, txrsp->id);
  12.488 -    }
  12.489 -
  12.490 -    xi->tx.rsp_cons = prod;
  12.491 -    /* resist the temptation to set the event more than +1... it breaks things */
  12.492 -    if (!dont_set_event)
  12.493 -      xi->tx.sring->rsp_event = prod + 1;
  12.494 -    KeMemoryBarrier();
  12.495 -  } while (prod != xi->tx.sring->rsp_prod);
  12.496 -
  12.497 -  /* if queued packets, send them now */
  12.498 -  if (!xi->tx_shutting_down)
  12.499 -    XenNet_SendQueuedPackets(xi);
  12.500 -
  12.501 -  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
  12.502 -
  12.503 -  /* must be done without holding any locks */
  12.504 -  while (head)
  12.505 -  {
  12.506 -    packet = (PNDIS_PACKET)head;
  12.507 -    head = *(PNDIS_PACKET *)&packet->MiniportReservedEx[0];
  12.508 -    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_SUCCESS);
  12.509 -    tx_packets++;
  12.510 -  }
  12.511 -
  12.512 -  /* must be done after we have truly given back all packets */
  12.513 -  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
  12.514 -  xi->tx_outstanding -= tx_packets;
  12.515 -  if (!xi->tx_outstanding && xi->tx_shutting_down)
  12.516 -    KeSetEvent(&xi->tx_idle_event, IO_NO_INCREMENT, FALSE);
  12.517 -  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
  12.518 -
  12.519 -  if (xi->device_state->suspend_resume_state_pdo == SR_STATE_SUSPENDING
  12.520 -    && xi->device_state->suspend_resume_state_fdo != SR_STATE_SUSPENDING
  12.521 -    && xi->tx_id_free == NET_TX_RING_SIZE)
  12.522 -  {
  12.523 -    KdPrint((__DRIVER_NAME "     Setting SR_STATE_SUSPENDING\n"));
  12.524 -    xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING;
  12.525 -    KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
  12.526 -    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
  12.527 -  }
  12.528 -
  12.529 -  //FUNCTION_EXIT();
  12.530 -}
  12.531 -
  12.532 -// called at <= DISPATCH_LEVEL
  12.533 -VOID
  12.534 -XenNet_SendPackets(
  12.535 -  IN NDIS_HANDLE MiniportAdapterContext,
  12.536 -  IN PPNDIS_PACKET PacketArray,
  12.537 -  IN UINT NumberOfPackets
  12.538 -  )
  12.539 -{
  12.540 -  struct xennet_info *xi = MiniportAdapterContext;
  12.541 -  PNDIS_PACKET packet;
  12.542 -  UINT i;
  12.543 -  PLIST_ENTRY entry;
  12.544 -  KIRQL OldIrql;
  12.545 -
  12.546 -  //FUNCTION_ENTER();
  12.547 -
  12.548 -  if (xi->inactive)
  12.549 -  {
  12.550 -    for (i = 0; i < NumberOfPackets; i++)
  12.551 -    {
  12.552 -      NdisMSendComplete(xi->adapter_handle, PacketArray[i], NDIS_STATUS_FAILURE);
  12.553 -    }
  12.554 -    return;
  12.555 -  }
  12.556 -    
  12.557 -  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
  12.558 -
  12.559 -  for (i = 0; i < NumberOfPackets; i++)
  12.560 -  {
  12.561 -    packet = PacketArray[i];
  12.562 -    ASSERT(packet);
  12.563 -    *(ULONG *)&packet->MiniportReservedEx = 0;
  12.564 -    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
  12.565 -    InsertTailList(&xi->tx_waiting_pkt_list, entry);
  12.566 -  }
  12.567 -
  12.568 -  XenNet_SendQueuedPackets(xi);
  12.569 -
  12.570 -  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
  12.571 -  
  12.572 -  //FUNCTION_EXIT();
  12.573 -}
  12.574 -
  12.575 -VOID
  12.576 -XenNet_CancelSendPackets(
  12.577 -  NDIS_HANDLE MiniportAdapterContext,
  12.578 -  PVOID CancelId)
  12.579 -{
  12.580 -  struct xennet_info *xi = MiniportAdapterContext;
  12.581 -  KIRQL old_irql;
  12.582 -  PLIST_ENTRY entry;
  12.583 -  PNDIS_PACKET packet;
  12.584 -  PNDIS_PACKET head = NULL, tail = NULL;
  12.585 -  BOOLEAN result;
  12.586 -
  12.587 -  FUNCTION_ENTER();
  12.588 -
  12.589 -  KeAcquireSpinLock(&xi->tx_lock, &old_irql);
  12.590 -
  12.591 -  entry = xi->tx_waiting_pkt_list.Flink;
  12.592 -  while (entry != &xi->tx_waiting_pkt_list)
  12.593 -  {
  12.594 -    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
  12.595 -    entry = entry->Flink;
  12.596 -    if (NDIS_GET_PACKET_CANCEL_ID(packet) == CancelId)
  12.597 -    {
  12.598 -      KdPrint((__DRIVER_NAME "     Found packet to cancel %p\n", packet));
  12.599 -      result = RemoveEntryList((PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)]);
  12.600 -      ASSERT(result);
  12.601 -      *(PNDIS_PACKET *)&packet->MiniportReservedEx[0] = NULL;
  12.602 -      if (head)
  12.603 -        *(PNDIS_PACKET *)&tail->MiniportReservedEx[0] = packet;
  12.604 -      else
  12.605 -        head = packet;
  12.606 -      tail = packet;
  12.607 -    }
  12.608 -  }
  12.609 -
  12.610 -  KeReleaseSpinLock(&xi->tx_lock, old_irql);
  12.611 -
  12.612 -  while (head)
  12.613 -  {
  12.614 -    packet = (PNDIS_PACKET)head;
  12.615 -    head = *(PNDIS_PACKET *)&packet->MiniportReservedEx[0];
  12.616 -    KdPrint((__DRIVER_NAME "     NdisMSendComplete(%p)\n", packet));
  12.617 -    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_REQUEST_ABORTED);
  12.618 -  }
  12.619 -  
  12.620 -  FUNCTION_EXIT();
  12.621 -}
  12.622 -
  12.623 -VOID
  12.624 -XenNet_TxResumeStart(xennet_info_t *xi)
  12.625 -{
  12.626 -  UNREFERENCED_PARAMETER(xi);
  12.627 -
  12.628 -  FUNCTION_ENTER();
  12.629 -    /* nothing to do here - all packets were already sent */
  12.630 -  FUNCTION_EXIT();
  12.631 -}
  12.632 -
  12.633 -VOID
  12.634 -XenNet_TxResumeEnd(xennet_info_t *xi)
  12.635 -{
  12.636 -  KIRQL old_irql;
  12.637 -
  12.638 -  FUNCTION_ENTER();
  12.639 -
  12.640 -  KeAcquireSpinLock(&xi->tx_lock, &old_irql);
  12.641 -  XenNet_SendQueuedPackets(xi);
  12.642 -  KeReleaseSpinLock(&xi->tx_lock, old_irql);
  12.643 -
  12.644 -  FUNCTION_EXIT();
  12.645 -}
  12.646 -
  12.647 -BOOLEAN
  12.648 -XenNet_TxInit(xennet_info_t *xi)
  12.649 -{
  12.650 -  USHORT i;
  12.651 -
  12.652 -  KeInitializeSpinLock(&xi->tx_lock);
  12.653 -  InitializeListHead(&xi->tx_waiting_pkt_list);
  12.654 -
  12.655 -  KeInitializeEvent(&xi->tx_idle_event, SynchronizationEvent, FALSE);
  12.656 -  xi->tx_shutting_down = FALSE;
  12.657 -  xi->tx_outstanding = 0;
  12.658 -  xi->tx_ring_free = NET_TX_RING_SIZE;
  12.659 -  
  12.660 -  NdisInitializeNPagedLookasideList(&xi->tx_lookaside_list, NULL, NULL, 0,
  12.661 -    PAGE_SIZE, XENNET_POOL_TAG, 0);
  12.662 -
  12.663 -  xi->tx_id_free = 0;
  12.664 -  for (i = 0; i < NET_TX_RING_SIZE; i++)
  12.665 -  {
  12.666 -    xi->tx_shadows[i].gref = INVALID_GRANT_REF;
  12.667 -    xi->tx_shadows[i].cb = NULL;
  12.668 -    put_id_on_freelist(xi, i);
  12.669 -  }
  12.670 -
  12.671 -  return TRUE;
  12.672 -}
  12.673 -
  12.674 -/*
  12.675 -The ring is completely closed down now. We just need to empty anything left
  12.676 -on our freelists and harvest anything left on the rings.
  12.677 -*/
  12.678 -
  12.679 -BOOLEAN
  12.680 -XenNet_TxShutdown(xennet_info_t *xi)
  12.681 -{
  12.682 -  PLIST_ENTRY entry;
  12.683 -  PNDIS_PACKET packet;
  12.684 -  //PMDL mdl;
  12.685 -  //ULONG i;
  12.686 -  KIRQL OldIrql;
  12.687 -
  12.688 -  FUNCTION_ENTER();
  12.689 -
  12.690 -  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
  12.691 -  xi->tx_shutting_down = TRUE;
  12.692 -  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
  12.693 -
  12.694 -  while (xi->tx_outstanding)
  12.695 -  {
  12.696 -    KdPrint((__DRIVER_NAME "     Waiting for %d remaining packets to be sent\n", xi->tx_outstanding));
  12.697 -    KeWaitForSingleObject(&xi->tx_idle_event, Executive, KernelMode, FALSE, NULL);
  12.698 -  }
  12.699 -
  12.700 -#if (NTDDI_VERSION >= NTDDI_WINXP)
  12.701 -  KeFlushQueuedDpcs();
  12.702 +#ifdef _GPLPV_NDIS5
  12.703 +#include "xennet5_tx.c"
  12.704 +#else
  12.705 +#include "xennet6_tx.c"
  12.706  #endif
  12.707 -
  12.708 -  /* Free packets in tx queue */
  12.709 -  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
  12.710 -  while (entry != &xi->tx_waiting_pkt_list)
  12.711 -  {
  12.712 -    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
  12.713 -    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
  12.714 -    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
  12.715 -  }
  12.716 -
  12.717 -  NdisDeleteNPagedLookasideList(&xi->tx_lookaside_list);
  12.718 -
  12.719 -  FUNCTION_EXIT();
  12.720 -
  12.721 -  return TRUE;
  12.722 -}