win-pvdrivers

changeset 204:9e4a4650518a

split tx, rx, and oid code out of xennet.c. Changes to send and receive code.
author James Harper <james.harper@bendigoit.com.au>
date Sun Mar 02 16:54:23 2008 +1100 (2008-03-02)
parents 2a3606fece27
children 3cc68cacff38
files common.inc xennet/sources xennet/xennet.c xennet/xennet.h xennet/xennet_oid.c xennet/xennet_rx.c xennet/xennet_tx.c
line diff
     1.1 --- a/common.inc	Sat Mar 01 00:40:44 2008 +1100
     1.2 +++ b/common.inc	Sun Mar 02 16:54:23 2008 +1100
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.4.31
     1.5 +VERSION=0.8.4.39
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7  KMDF_VERSION=1
     1.8  !IF $(_NT_TOOLS_VERSION) > 0x700
     2.1 --- a/xennet/sources	Sat Mar 01 00:40:44 2008 +1100
     2.2 +++ b/xennet/sources	Sun Mar 02 16:54:23 2008 +1100
     2.3 @@ -4,4 +4,4 @@ TARGETTYPE=DRIVER
     2.4  INF_NAME=$(TARGETNAME)
     2.5  TARGETLIBS=$(TARGETLIBS) $(DDK_LIB_PATH)\ndis.lib
     2.6  MISCFILES=..\Target\$(DDK_TARGET_OS)\$(INF_NAME).inf
     2.7 -SOURCES=xennet.c
     2.8 +SOURCES=xennet.c xennet_tx.c xennet_rx.c xennet_oid.c
     3.1 --- a/xennet/xennet.c	Sat Mar 01 00:40:44 2008 +1100
     3.2 +++ b/xennet/xennet.c	Sun Mar 02 16:54:23 2008 +1100
     3.3 @@ -22,141 +22,29 @@ Foundation, Inc., 51 Franklin Street, Fi
     3.4  #include <io/xenbus.h>
     3.5  #include "xennet.h"
     3.6  
     3.7 -/* Xen macros use these, so they need to be redefined to Win equivs */
     3.8 -#define wmb() KeMemoryBarrier()
     3.9 -#define mb() KeMemoryBarrier()
    3.10 -
    3.11 -//#if !defined (NDIS51_MINIPORT)
    3.12 -//#error requires NDIS 5.1 compilation environment
    3.13 -//#endif
    3.14 -
    3.15 -#define GRANT_INVALID_REF 0
    3.16 -
    3.17 -/* couldn't get regular xen ring macros to work...*/
    3.18 -#define __NET_RING_SIZE(type, _sz) \
    3.19 -    (__RD32( \
    3.20 -    (_sz - sizeof(struct type##_sring) + sizeof(union type##_sring_entry)) \
    3.21 -    / sizeof(union type##_sring_entry)))
    3.22 -
    3.23 -#define NET_TX_RING_SIZE __NET_RING_SIZE(netif_tx, PAGE_SIZE)
    3.24 -#define NET_RX_RING_SIZE __NET_RING_SIZE(netif_rx, PAGE_SIZE)
    3.25 -
    3.26 -#pragma warning(disable: 4127) // conditional expression is constant
    3.27 -
    3.28 -struct _buffer_entry
    3.29 -{
    3.30 -  char data[PAGE_SIZE - sizeof(LIST_ENTRY) - sizeof(PNDIS_BUFFER)];
    3.31 -  LIST_ENTRY entry;
    3.32 -  PNDIS_BUFFER buffer;
    3.33 -} typedef buffer_entry_t;
    3.34 -
    3.35 -static LARGE_INTEGER ProfTime_TxBufferGC;
    3.36 -static LARGE_INTEGER ProfTime_TxBufferFree;
    3.37 -static LARGE_INTEGER ProfTime_RxBufferAlloc;
    3.38 -static LARGE_INTEGER ProfTime_RxBufferFree;
    3.39 -static LARGE_INTEGER ProfTime_ReturnPacket;
    3.40 -static LARGE_INTEGER ProfTime_RxBufferCheck;
    3.41 -static LARGE_INTEGER ProfTime_Linearize;
    3.42 -static LARGE_INTEGER ProfTime_SendPackets;
    3.43 -static LARGE_INTEGER ProfTime_SendQueuedPackets;
    3.44 -static LARGE_INTEGER ProfTime_GrantAccess;
    3.45 -static LARGE_INTEGER ProfTime_EndAccess;
    3.46 -
    3.47 -static int ProfCount_TxBufferGC;
    3.48 -static int ProfCount_TxBufferFree;
    3.49 -static int ProfCount_RxBufferAlloc;
    3.50 -static int ProfCount_RxBufferFree;
    3.51 -static int ProfCount_ReturnPacket;
    3.52 -static int ProfCount_RxBufferCheck;
    3.53 -static int ProfCount_Linearize;
    3.54 -static int ProfCount_SendPackets;
    3.55 -static int ProfCount_SendQueuedPackets;
    3.56 -static int ProfCount_GrantAccess;
    3.57 -static int ProfCount_EndAccess;
    3.58 -
    3.59 -struct xennet_info
    3.60 -{
    3.61 -  /* Base device vars */
    3.62 -  PDEVICE_OBJECT pdo;
    3.63 -  PDEVICE_OBJECT fdo;
    3.64 -  PDEVICE_OBJECT lower_do;
    3.65 -  WDFDEVICE wdf_device;
    3.66 -  WCHAR dev_desc[NAME_SIZE];
    3.67 +LARGE_INTEGER ProfTime_TxBufferGC;
    3.68 +LARGE_INTEGER ProfTime_TxBufferFree;
    3.69 +LARGE_INTEGER ProfTime_RxBufferAlloc;
    3.70 +LARGE_INTEGER ProfTime_RxBufferFree;
    3.71 +LARGE_INTEGER ProfTime_ReturnPacket;
    3.72 +LARGE_INTEGER ProfTime_RxBufferCheck;
    3.73 +LARGE_INTEGER ProfTime_Linearize;
    3.74 +LARGE_INTEGER ProfTime_SendPackets;
    3.75 +LARGE_INTEGER ProfTime_SendQueuedPackets;
    3.76 +LARGE_INTEGER ProfTime_GrantAccess;
    3.77 +LARGE_INTEGER ProfTime_EndAccess;
    3.78  
    3.79 -  /* NDIS-related vars */
    3.80 -  NDIS_HANDLE adapter_handle;
    3.81 -  NDIS_HANDLE packet_pool;
    3.82 -  NDIS_HANDLE buffer_pool;
    3.83 -  ULONG packet_filter;
    3.84 -  int connected;
    3.85 -  UINT8 perm_mac_addr[ETH_ALEN];
    3.86 -  UINT8 curr_mac_addr[ETH_ALEN];
    3.87 -
    3.88 -  /* Misc. Xen vars */
    3.89 -  XEN_IFACE XenInterface;
    3.90 -  PXENPCI_XEN_DEVICE_DATA pdo_data;
    3.91 -  evtchn_port_t event_channel;
    3.92 -  ULONG state;
    3.93 -  KEVENT backend_state_change_event;
    3.94 -  KEVENT shutdown_event;
    3.95 -  char backend_path[MAX_XENBUS_STR_LEN];
    3.96 -  ULONG backend_state;
    3.97 -
    3.98 -  /* Xen ring-related vars */
    3.99 -  KSPIN_LOCK rx_lock;
   3.100 -  KSPIN_LOCK tx_lock;
   3.101 -
   3.102 -  LIST_ENTRY tx_waiting_pkt_list;
   3.103 -  LIST_ENTRY rx_free_buf_list;
   3.104 -
   3.105 -  struct netif_tx_front_ring tx;
   3.106 -  struct netif_rx_front_ring rx;
   3.107 -  grant_ref_t tx_ring_ref;
   3.108 -  grant_ref_t rx_ring_ref;
   3.109 -
   3.110 -  /* ptrs to the actual rings themselvves */
   3.111 -  struct netif_tx_sring *tx_pgs;
   3.112 -  struct netif_rx_sring *rx_pgs;
   3.113 -
   3.114 -  
   3.115 -  PMDL page_list[NET_TX_RING_SIZE + 1 + NET_RX_RING_SIZE];
   3.116 -  ULONG page_free;
   3.117 -  KSPIN_LOCK page_lock;
   3.118 -
   3.119 -  /* MDLs for the above */
   3.120 -  PMDL tx_mdl;
   3.121 -  PMDL rx_mdl;
   3.122 -
   3.123 -  /* Packets given to netback. The first entry in tx_pkts
   3.124 -   * is an index into a chain of free entries. */
   3.125 -  int tx_pkt_ids_used;
   3.126 -  PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE+1];
   3.127 -  PNDIS_BUFFER rx_buffers[NET_RX_RING_SIZE];
   3.128 -
   3.129 -//  grant_ref_t gref_tx_head;
   3.130 -  grant_ref_t grant_tx_ref[NET_TX_RING_SIZE+1];
   3.131 -//  grant_ref_t gref_rx_head;
   3.132 -  grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
   3.133 -
   3.134 -  /* Receive-ring batched refills. */
   3.135 -#define RX_MIN_TARGET 8
   3.136 -#define RX_DFL_MIN_TARGET 64
   3.137 -#define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
   3.138 -  ULONG rx_target;
   3.139 -  ULONG rx_max_target;
   3.140 -  ULONG rx_min_target;
   3.141 -
   3.142 -  /* how many packets are in the net stack atm */
   3.143 -  LONG rx_outstanding;
   3.144 -  LONG tx_outstanding;
   3.145 -
   3.146 -  /* stats */
   3.147 -  ULONG64 stat_tx_ok;
   3.148 -  ULONG64 stat_rx_ok;
   3.149 -  ULONG64 stat_tx_error;
   3.150 -  ULONG64 stat_rx_error;
   3.151 -  ULONG64 stat_rx_no_buffer;
   3.152 -};
   3.153 +int ProfCount_TxBufferGC;
   3.154 +int ProfCount_TxBufferFree;
   3.155 +int ProfCount_RxBufferAlloc;
   3.156 +int ProfCount_RxBufferFree;
   3.157 +int ProfCount_ReturnPacket;
   3.158 +int ProfCount_RxBufferCheck;
   3.159 +int ProfCount_Linearize;
   3.160 +int ProfCount_SendPackets;
   3.161 +int ProfCount_SendQueuedPackets;
   3.162 +int ProfCount_GrantAccess;
   3.163 +int ProfCount_EndAccess;
   3.164  
   3.165  /* This function copied from linux's lib/vsprintf.c, see it for attribution */
   3.166  static unsigned long
   3.167 @@ -188,27 +76,7 @@ simple_strtoul(const char *cp,char **end
   3.168    return result;
   3.169  }
   3.170  
   3.171 -static void
   3.172 -add_id_to_freelist(struct xennet_info *xi, unsigned short id)
   3.173 -{
   3.174 -  xi->tx_pkts[id] = xi->tx_pkts[0];
   3.175 -  xi->tx_pkts[0]  = IntToPtr(id);
   3.176 -  xi->tx_pkt_ids_used--;
   3.177 -}
   3.178 -
   3.179 -static unsigned short
   3.180 -get_id_from_freelist(struct xennet_info *xi)
   3.181 -{
   3.182 -  unsigned short id;
   3.183 -  if (xi->tx_pkt_ids_used >= NET_TX_RING_SIZE)
   3.184 -    return 0;
   3.185 -  id = (unsigned short)(unsigned long)xi->tx_pkts[0];
   3.186 -  xi->tx_pkts[0] = xi->tx_pkts[id];
   3.187 -  xi->tx_pkt_ids_used++;
   3.188 -  return id;
   3.189 -}
   3.190 -
   3.191 -static PMDL
   3.192 +PMDL
   3.193  get_page_from_freelist(struct xennet_info *xi)
   3.194  {
   3.195    PMDL mdl;
   3.196 @@ -241,13 +109,23 @@ get_page_from_freelist(struct xennet_inf
   3.197    return mdl;
   3.198  }
   3.199  
   3.200 -static __inline grant_ref_t
   3.201 -get_grant_ref(PMDL mdl)
   3.202 +VOID
   3.203 +free_page_freelist(struct xennet_info *xi)
   3.204  {
   3.205 -  return *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE));
   3.206 +  PMDL mdl;
   3.207 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.208 +
   3.209 +  while(xi->page_free != 0)
   3.210 +  {
   3.211 +    xi->page_free--;
   3.212 +    mdl = xi->page_list[xi->page_free];
   3.213 +    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   3.214 +      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)));
   3.215 +    FreePages(mdl);
   3.216 +  }
   3.217  }
   3.218  
   3.219 -static VOID
   3.220 +VOID
   3.221  put_page_on_freelist(struct xennet_info *xi, PMDL mdl)
   3.222  {
   3.223    KIRQL OldIrql;
   3.224 @@ -264,409 +142,6 @@ put_page_on_freelist(struct xennet_info 
   3.225    KeReleaseSpinLock(&xi->page_lock, OldIrql);
   3.226  
   3.227  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.228 -
   3.229 -/*
   3.230 -  xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   3.231 -        *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)));
   3.232 -*/
   3.233 -}
   3.234 -
   3.235 -static VOID
   3.236 -XenNet_SendQueuedPackets(struct xennet_info *xi);
   3.237 -
   3.238 -// Called at DISPATCH_LEVEL
   3.239 -static NDIS_STATUS
   3.240 -XenNet_TxBufferGC(struct xennet_info *xi)
   3.241 -{
   3.242 -  RING_IDX cons, prod;
   3.243 -  unsigned short id;
   3.244 -  PNDIS_PACKET pkt;
   3.245 -  LARGE_INTEGER tsc, dummy;
   3.246 -  int moretodo;
   3.247 -//  LARGE_INTEGER gtsc;
   3.248 -
   3.249 -  ASSERT(xi->connected);
   3.250 -  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
   3.251 -
   3.252 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.253 -
   3.254 -  tsc = KeQueryPerformanceCounter(&dummy);
   3.255 -
   3.256 -  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
   3.257 -
   3.258 -  do {
   3.259 -    prod = xi->tx.sring->rsp_prod;
   3.260 -    KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
   3.261 -
   3.262 -    for (cons = xi->tx.rsp_cons; cons != prod; cons++) {
   3.263 -      struct netif_tx_response *txrsp;
   3.264 -
   3.265 -      txrsp = RING_GET_RESPONSE(&xi->tx, cons);
   3.266 -      if (txrsp->status == NETIF_RSP_NULL)
   3.267 -        continue;
   3.268 -
   3.269 -      id  = txrsp->id;
   3.270 -      pkt = xi->tx_pkts[id];
   3.271 -/*
   3.272 -gtsc = KeQueryPerformanceCounter(&dummy);
   3.273 -      xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   3.274 -        xi->grant_tx_ref[id]);
   3.275 -ProfTime_EndAccess.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - gtsc.QuadPart;
   3.276 -ProfCount_EndAccess++;
   3.277 -*/
   3.278 -      xi->grant_tx_ref[id] = GRANT_INVALID_REF;
   3.279 -      add_id_to_freelist(xi, id);
   3.280 -
   3.281 -      put_page_on_freelist(xi, *(PMDL *)pkt->MiniportReservedEx);
   3.282 -
   3.283 -      InterlockedDecrement(&xi->tx_outstanding);
   3.284 -      xi->stat_tx_ok++;
   3.285 -      NdisMSendComplete(xi->adapter_handle, pkt, NDIS_STATUS_SUCCESS);
   3.286 -    }
   3.287 -
   3.288 -    xi->tx.rsp_cons = prod;
   3.289 -
   3.290 -    RING_FINAL_CHECK_FOR_RESPONSES(&xi->tx, moretodo);
   3.291 -  } while (moretodo);
   3.292 -
   3.293 -  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   3.294 -
   3.295 -  /* if queued packets, send them now */
   3.296 -  XenNet_SendQueuedPackets(xi);
   3.297 -
   3.298 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.299 -
   3.300 -  ProfTime_TxBufferGC.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   3.301 -  ProfCount_TxBufferGC++;
   3.302 -
   3.303 -  return NDIS_STATUS_SUCCESS;
   3.304 -}
   3.305 -
   3.306 -static void
   3.307 -XenNet_TxBufferFree(struct xennet_info *xi)
   3.308 -{
   3.309 -  PNDIS_PACKET packet;
   3.310 -  PMDL pmdl;
   3.311 -  PLIST_ENTRY entry;
   3.312 -  unsigned short id;
   3.313 -  PVOID ptr;
   3.314 -
   3.315 -  ASSERT(!xi->connected);
   3.316 -
   3.317 -  /* Free packets in tx queue */
   3.318 -  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   3.319 -  while (entry != &xi->tx_waiting_pkt_list)
   3.320 -  {
   3.321 -    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   3.322 -
   3.323 -    put_page_on_freelist(xi, *(PMDL *)packet->MiniportReservedEx);
   3.324 -
   3.325 -    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   3.326 -    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   3.327 -  }
   3.328 -
   3.329 -  /* free sent-but-not-completed packets */
   3.330 -  for (id = 1; id < NET_TX_RING_SIZE+1; id++) {
   3.331 -    if (xi->grant_tx_ref[id] == GRANT_INVALID_REF)
   3.332 -      continue;
   3.333 -
   3.334 -    packet = xi->tx_pkts[id];
   3.335 -/*
   3.336 -    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   3.337 -      xi->grant_tx_ref[id]);
   3.338 -    xi->grant_tx_ref[id] = GRANT_INVALID_REF;
   3.339 -*/
   3.340 -    add_id_to_freelist(xi, id);
   3.341 -
   3.342 -    /* free linearized data page */
   3.343 -    pmdl = *(PMDL *)packet->MiniportReservedEx;
   3.344 -    ptr = MmGetMdlVirtualAddress(pmdl);
   3.345 -    IoFreeMdl(pmdl);
   3.346 -    NdisFreeMemory(ptr, 0, 0); // <= DISPATCH_LEVEL
   3.347 -
   3.348 -    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   3.349 -  }
   3.350 -}
   3.351 -
   3.352 -// Called at DISPATCH_LEVEL with rx lock held
   3.353 -
   3.354 -static NDIS_STATUS
   3.355 -XenNet_RxBufferAlloc(struct xennet_info *xi)
   3.356 -{
   3.357 -  unsigned short id;
   3.358 -  PNDIS_BUFFER buffer;
   3.359 -  int i, batch_target, notify;
   3.360 -  RING_IDX req_prod = xi->rx.req_prod_pvt;
   3.361 -  grant_ref_t ref;
   3.362 -  netif_rx_request_t *req;
   3.363 -  PLIST_ENTRY entry;
   3.364 -  buffer_entry_t *buffer_entry;
   3.365 -  NDIS_STATUS status;
   3.366 -  LARGE_INTEGER tsc, dummy;
   3.367 -  LARGE_INTEGER gtsc;
   3.368 -
   3.369 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.370 -  tsc = KeQueryPerformanceCounter(&dummy);
   3.371 -
   3.372 -  batch_target = xi->rx_target - (req_prod - xi->rx.rsp_cons);
   3.373 -
   3.374 -  for (i = 0; i < batch_target; i++)
   3.375 -  {
   3.376 -    /* reuse entries off the free buffer list, unless it's exhausted */
   3.377 -    entry = RemoveHeadList(&xi->rx_free_buf_list);
   3.378 -    if (entry != &xi->rx_free_buf_list)
   3.379 -    {
   3.380 -      buffer = CONTAINING_RECORD(entry, buffer_entry_t, entry)->buffer;
   3.381 -    }
   3.382 -    else
   3.383 -    {
   3.384 -      status = NdisAllocateMemoryWithTag(&buffer_entry,
   3.385 -        sizeof(buffer_entry_t), XENNET_POOL_TAG);
   3.386 -      if (status != NDIS_STATUS_SUCCESS)
   3.387 -      {
   3.388 -        KdPrint(("NdisAllocateMemoryWithTag Failed! status = 0x%x\n", status));
   3.389 -        break;
   3.390 -      }
   3.391 -      NdisAllocateBuffer(&status, &buffer_entry->buffer, xi->buffer_pool,
   3.392 -        buffer_entry, sizeof(buffer_entry->data));
   3.393 -      ASSERT(status == NDIS_STATUS_SUCCESS); // should never fail
   3.394 -      buffer = buffer_entry->buffer;
   3.395 -    }
   3.396 -
   3.397 -    /* Give to netback */
   3.398 -    id = (unsigned short)(req_prod + i) & (NET_RX_RING_SIZE - 1);
   3.399 -    ASSERT(!xi->rx_buffers[id]);
   3.400 -    xi->rx_buffers[id] = buffer;
   3.401 -    req = RING_GET_REQUEST(&xi->rx, req_prod + i);
   3.402 -    /* an NDIS_BUFFER is just a MDL, so we can get its pfn array */
   3.403 -gtsc = KeQueryPerformanceCounter(&dummy);
   3.404 -    ref = xi->XenInterface.GntTbl_GrantAccess(
   3.405 -      xi->XenInterface.InterfaceHeader.Context, 0,
   3.406 -      *MmGetMdlPfnArray(buffer), FALSE);
   3.407 -ProfTime_GrantAccess.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - gtsc.QuadPart;
   3.408 -ProfCount_GrantAccess++;
   3.409 -    ASSERT((signed short)ref >= 0);
   3.410 -    xi->grant_rx_ref[id] = ref;
   3.411 -
   3.412 -    req->id = id;
   3.413 -    req->gref = ref;
   3.414 -  }
   3.415 -
   3.416 -  xi->rx.req_prod_pvt = req_prod + i;
   3.417 -  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->rx, notify);
   3.418 -  if (notify)
   3.419 -  {
   3.420 -    xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
   3.421 -      xi->event_channel);
   3.422 -  }
   3.423 -
   3.424 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.425 -
   3.426 -  ProfTime_RxBufferAlloc.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   3.427 -  ProfCount_RxBufferAlloc++;
   3.428 -
   3.429 -  return NDIS_STATUS_SUCCESS;
   3.430 -}
   3.431 -
   3.432 -/* Free all Rx buffers (on halt, for example) */
   3.433 -static void
   3.434 -XenNet_RxBufferFree(struct xennet_info *xi)
   3.435 -{
   3.436 -  int i;
   3.437 -  grant_ref_t ref;
   3.438 -  PNDIS_BUFFER buffer;
   3.439 -  KIRQL OldIrql;
   3.440 -  PVOID buff_va;
   3.441 -  PLIST_ENTRY entry;
   3.442 -  int ungranted;
   3.443 -  LARGE_INTEGER tsc, dummy;
   3.444 -
   3.445 -  ASSERT(!xi->connected);
   3.446 -
   3.447 -  tsc = KeQueryPerformanceCounter(&dummy);
   3.448 -
   3.449 -  KeAcquireSpinLock(&xi->rx_lock, &OldIrql);
   3.450 -
   3.451 -  for (i = 0; i < NET_RX_RING_SIZE; i++)
   3.452 -  {
   3.453 -    if (!xi->rx_buffers[i])
   3.454 -      continue;
   3.455 -
   3.456 -    buffer = xi->rx_buffers[i];
   3.457 -    ref = xi->grant_rx_ref[i];
   3.458 -
   3.459 -    /* don't check return, what can we do about it on failure? */
   3.460 -    ungranted = xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context, ref);
   3.461 -
   3.462 -    NdisAdjustBufferLength(buffer, sizeof(buffer_entry_t));
   3.463 -    buff_va = NdisBufferVirtualAddressSafe(buffer, NormalPagePriority);
   3.464 -    NdisFreeBuffer(buffer);
   3.465 -    if (ungranted)
   3.466 -    {
   3.467 -      NdisFreeMemory(buff_va, 0, 0); // <= DISPATCH_LEVEL
   3.468 -    }
   3.469 -  }
   3.470 -
   3.471 -  while ((entry = RemoveHeadList(&xi->rx_free_buf_list)) != &xi->rx_free_buf_list)
   3.472 -  {
   3.473 -    buffer = CONTAINING_RECORD(entry, buffer_entry_t, entry)->buffer;
   3.474 -    NdisAdjustBufferLength(buffer, sizeof(buffer_entry_t));
   3.475 -    buff_va = NdisBufferVirtualAddressSafe(buffer, NormalPagePriority);
   3.476 -    NdisFreeBuffer(buffer);
   3.477 -    NdisFreeMemory(buff_va, 0, 0); // <= DISPATCH_LEVEL
   3.478 -  }
   3.479 -
   3.480 -  KeReleaseSpinLock(&xi->rx_lock, OldIrql);
   3.481 -
   3.482 -  ProfTime_RxBufferFree.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   3.483 -  ProfCount_RxBufferFree++;
   3.484 -}
   3.485 -
   3.486 -VOID
   3.487 -XenNet_ReturnPacket(
   3.488 -  IN NDIS_HANDLE MiniportAdapterContext,
   3.489 -  IN PNDIS_PACKET Packet
   3.490 -  )
   3.491 -{
   3.492 -  struct xennet_info *xi = MiniportAdapterContext;
   3.493 -  PNDIS_BUFFER buffer;
   3.494 -  buffer_entry_t *buffer_entry;
   3.495 -  LARGE_INTEGER tsc, dummy;
   3.496 -
   3.497 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.498 -
   3.499 -  tsc = KeQueryPerformanceCounter(&dummy);
   3.500 -
   3.501 -  NdisUnchainBufferAtBack(Packet, &buffer);
   3.502 -  while (buffer)
   3.503 -  {
   3.504 -    NdisAdjustBufferLength(buffer, sizeof(buffer_entry_t));
   3.505 -    buffer_entry = NdisBufferVirtualAddressSafe(buffer, NormalPagePriority);
   3.506 -    InsertTailList(&xi->rx_free_buf_list, &buffer_entry->entry);
   3.507 -    NdisUnchainBufferAtBack(Packet, &buffer);
   3.508 -  }
   3.509 -
   3.510 -  NdisFreePacket(Packet);
   3.511 -  
   3.512 -  InterlockedDecrement(&xi->rx_outstanding);
   3.513 -
   3.514 -  // if we are no longer connected then _halt needs to know when rx_outstanding reaches zero
   3.515 -  if (!xi->connected && !xi->rx_outstanding)
   3.516 -    KeSetEvent(&xi->shutdown_event, 1, FALSE);  
   3.517 -
   3.518 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.519 -
   3.520 -  ProfTime_ReturnPacket.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   3.521 -  ProfCount_ReturnPacket++;
   3.522 -}
   3.523 -
   3.524 -// Called at DISPATCH_LEVEL
   3.525 -static NDIS_STATUS
   3.526 -XenNet_RxBufferCheck(struct xennet_info *xi)
   3.527 -{
   3.528 -  RING_IDX cons, prod;
   3.529 -  PNDIS_PACKET packets[NET_RX_RING_SIZE];
   3.530 -  ULONG packet_count;
   3.531 -  PNDIS_BUFFER buffer;
   3.532 -  int moretodo;
   3.533 -  KIRQL OldIrql;
   3.534 -  struct netif_rx_response *rxrsp = NULL;
   3.535 -  int more_frags = 0;
   3.536 -  NDIS_STATUS status;
   3.537 -  LARGE_INTEGER tsc, dummy;
   3.538 -  LARGE_INTEGER time_received;
   3.539 -  LARGE_INTEGER gtsc;
   3.540 -  
   3.541 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.542 -
   3.543 -  tsc = KeQueryPerformanceCounter(&dummy);
   3.544 -
   3.545 -  ASSERT(xi->connected);
   3.546 -
   3.547 -  NdisGetCurrentSystemTime(&time_received);
   3.548 -  KeAcquireSpinLock(&xi->rx_lock, &OldIrql);
   3.549 -
   3.550 -  packet_count = 0;
   3.551 -  do {
   3.552 -    prod = xi->rx.sring->rsp_prod;
   3.553 -    KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
   3.554 -
   3.555 -    for (cons = xi->rx.rsp_cons; cons != prod; cons++) {
   3.556 -
   3.557 -      rxrsp = RING_GET_RESPONSE(&xi->rx, cons);
   3.558 -      if (rxrsp->status <= 0
   3.559 -        || rxrsp->offset + rxrsp->status > PAGE_SIZE)
   3.560 -      {
   3.561 -        KdPrint((__DRIVER_NAME ": Error: rxrsp offset %d, size %d\n",
   3.562 -          rxrsp->offset, rxrsp->status));
   3.563 -        continue;
   3.564 -      }
   3.565 -
   3.566 -      if (!more_frags) // handling the packet's 1st buffer
   3.567 -      {
   3.568 -        NdisAllocatePacket(&status, &packets[packet_count], xi->packet_pool);
   3.569 -        ASSERT(status == NDIS_STATUS_SUCCESS);
   3.570 -        NDIS_SET_PACKET_HEADER_SIZE(packets[packet_count], XN_HDR_SIZE);
   3.571 -      }
   3.572 -
   3.573 -      buffer = xi->rx_buffers[rxrsp->id];
   3.574 -      xi->rx_buffers[rxrsp->id] = NULL;
   3.575 -      NdisAdjustBufferLength(buffer, rxrsp->status);
   3.576 -      NdisChainBufferAtBack(packets[packet_count], buffer);
   3.577 -gtsc = KeQueryPerformanceCounter(&dummy);
   3.578 -      xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
   3.579 -        xi->grant_rx_ref[rxrsp->id]);
   3.580 -ProfTime_EndAccess.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - gtsc.QuadPart;
   3.581 -ProfCount_EndAccess++;
   3.582 -
   3.583 -      xi->grant_rx_ref[rxrsp->id] = GRANT_INVALID_REF;
   3.584 -
   3.585 -      ASSERT(!(rxrsp->flags & NETRXF_extra_info)); // not used on RX
   3.586 -
   3.587 -      more_frags = rxrsp->flags & NETRXF_more_data;
   3.588 -
   3.589 -      /* Packet done, pass it up */
   3.590 -      if (!more_frags)
   3.591 -      {
   3.592 -        xi->stat_rx_ok++;
   3.593 -        InterlockedIncrement(&xi->rx_outstanding);
   3.594 -        NDIS_SET_PACKET_STATUS(packets[packet_count], NDIS_STATUS_SUCCESS);
   3.595 -        NDIS_SET_PACKET_TIME_RECEIVED(packets[packet_count], time_received.QuadPart);
   3.596 -        packet_count++;
   3.597 -        if (packet_count == NET_RX_RING_SIZE)
   3.598 -        {
   3.599 -          NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
   3.600 -          packet_count = 0;
   3.601 -        }
   3.602 -      }
   3.603 -    }
   3.604 -    xi->rx.rsp_cons = prod;
   3.605 -
   3.606 -    RING_FINAL_CHECK_FOR_RESPONSES(&xi->rx, moretodo);
   3.607 -  } while (moretodo);
   3.608 -
   3.609 -  if (more_frags)
   3.610 -  {
   3.611 -    KdPrint((__DRIVER_NAME "     Missing fragments\n"));
   3.612 -    XenNet_ReturnPacket(xi, packets[packet_count]);
   3.613 -  }
   3.614 -
   3.615 -  if (packet_count != 0)
   3.616 -  {
   3.617 -    NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
   3.618 -  }
   3.619 -
   3.620 -  /* Give netback more buffers */
   3.621 -  XenNet_RxBufferAlloc(xi);
   3.622 -
   3.623 -  KeReleaseSpinLock(&xi->rx_lock, OldIrql);
   3.624 -
   3.625 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.626 -
   3.627 -  ProfTime_RxBufferCheck.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   3.628 -  ProfCount_RxBufferCheck++;
   3.629 -
   3.630 -  return NDIS_STATUS_SUCCESS;
   3.631  }
   3.632  
   3.633  // Called at DISPATCH_LEVEL
   3.634 @@ -802,7 +277,6 @@ XenNet_Init(
   3.635    int retry = 0;
   3.636    char *err;
   3.637    xenbus_transaction_t xbt = 0;
   3.638 -  KIRQL OldIrql;
   3.639  
   3.640    UNREFERENCED_PARAMETER(OpenErrorStatus);
   3.641    UNREFERENCED_PARAMETER(WrapperConfigurationContext);
   3.642 @@ -848,7 +322,6 @@ XenNet_Init(
   3.643    KeInitializeSpinLock(&xi->tx_lock);
   3.644    KeInitializeSpinLock(&xi->rx_lock);
   3.645  
   3.646 -  InitializeListHead(&xi->rx_free_buf_list);
   3.647    InitializeListHead(&xi->tx_waiting_pkt_list);
   3.648  
   3.649    KeInitializeSpinLock(&xi->page_lock);
   3.650 @@ -876,16 +349,6 @@ XenNet_Init(
   3.651      &xi->lower_do, NULL, NULL);
   3.652    xi->pdo_data = (PXENPCI_XEN_DEVICE_DATA)xi->pdo->DeviceExtension;
   3.653  
   3.654 -  /* Initialize tx_pkts as a free chain containing every entry. */
   3.655 -  for (i = 0; i < NET_TX_RING_SIZE+1; i++) {
   3.656 -    xi->tx_pkts[i] = IntToPtr(i + 1);
   3.657 -    xi->grant_tx_ref[i] = GRANT_INVALID_REF;
   3.658 -  }
   3.659 -  for (i = 0; i < NET_RX_RING_SIZE; i++) {
   3.660 -    xi->rx_buffers[i] = NULL;
   3.661 -    xi->grant_rx_ref[i] = GRANT_INVALID_REF;
   3.662 -  }
   3.663 -
   3.664    xi->packet_filter = NDIS_PACKET_TYPE_PROMISCUOUS;
   3.665  
   3.666    status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
   3.667 @@ -960,21 +423,8 @@ XenNet_Init(
   3.668    xi->XenInterface.EvtChn_BindDpc(xi->XenInterface.InterfaceHeader.Context,
   3.669      xi->event_channel, XenNet_Interrupt, xi);
   3.670  
   3.671 -  xi->tx_mdl = AllocatePage();
   3.672 -  xi->tx_pgs = MmGetMdlVirtualAddress(xi->tx_mdl);
   3.673 -  SHARED_RING_INIT(xi->tx_pgs);
   3.674 -  FRONT_RING_INIT(&xi->tx, xi->tx_pgs, PAGE_SIZE);
   3.675 -  xi->tx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
   3.676 -    xi->XenInterface.InterfaceHeader.Context, 0,
   3.677 -    *MmGetMdlPfnArray(xi->tx_mdl), FALSE);
   3.678 -
   3.679 -  xi->rx_mdl = AllocatePage();
   3.680 -  xi->rx_pgs = MmGetMdlVirtualAddress(xi->rx_mdl);
   3.681 -  SHARED_RING_INIT(xi->rx_pgs);
   3.682 -  FRONT_RING_INIT(&xi->rx, xi->rx_pgs, PAGE_SIZE);
   3.683 -  xi->rx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
   3.684 -    xi->XenInterface.InterfaceHeader.Context, 0,
   3.685 -    *MmGetMdlPfnArray(xi->rx_mdl), FALSE);
   3.686 +  XenNet_TxInit(xi);
   3.687 +  XenNet_RxInit(xi);
   3.688  
   3.689    /* fixup array for dynamic values */
   3.690    params[0].value = xi->tx_ring_ref;
   3.691 @@ -1022,10 +472,6 @@ XenNet_Init(
   3.692  
   3.693    KdPrint((__DRIVER_NAME "     Connected\n"));
   3.694  
   3.695 -  KeAcquireSpinLock(&xi->rx_lock, &OldIrql);
   3.696 -  XenNet_RxBufferAlloc(xi);
   3.697 -  KeReleaseSpinLock(&xi->rx_lock, OldIrql);
   3.698 -
   3.699    /* get mac address */
   3.700    RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/mac", xi->backend_path);
   3.701    xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
   3.702 @@ -1066,698 +512,6 @@ err:
   3.703    return status;
   3.704  }
   3.705  
   3.706 -// Q = Query Mandatory, S = Set Mandatory
   3.707 -NDIS_OID supported_oids[] =
   3.708 -{
   3.709 -  /* general OIDs */
   3.710 -  OID_GEN_SUPPORTED_LIST,        // Q
   3.711 -  OID_GEN_HARDWARE_STATUS,       // Q
   3.712 -  OID_GEN_MEDIA_SUPPORTED,       // Q
   3.713 -  OID_GEN_MEDIA_IN_USE,          // Q
   3.714 -  OID_GEN_MAXIMUM_LOOKAHEAD,     // Q
   3.715 -  OID_GEN_MAXIMUM_FRAME_SIZE,    // Q
   3.716 -  OID_GEN_LINK_SPEED,            // Q
   3.717 -  OID_GEN_TRANSMIT_BUFFER_SPACE, // Q
   3.718 -  OID_GEN_RECEIVE_BUFFER_SPACE,  // Q
   3.719 -  OID_GEN_TRANSMIT_BLOCK_SIZE,   // Q
   3.720 -  OID_GEN_RECEIVE_BLOCK_SIZE,    // Q
   3.721 -  OID_GEN_VENDOR_ID,             // Q
   3.722 -  OID_GEN_VENDOR_DESCRIPTION,    // Q
   3.723 -  OID_GEN_CURRENT_PACKET_FILTER, // QS
   3.724 -  OID_GEN_CURRENT_LOOKAHEAD,     // QS
   3.725 -  OID_GEN_DRIVER_VERSION,        // Q
   3.726 -  OID_GEN_MAXIMUM_TOTAL_SIZE,    // Q
   3.727 -  OID_GEN_PROTOCOL_OPTIONS,      // S
   3.728 -  OID_GEN_MAC_OPTIONS,           // Q
   3.729 -  OID_GEN_MEDIA_CONNECT_STATUS,  // Q
   3.730 -  OID_GEN_MAXIMUM_SEND_PACKETS,  // Q
   3.731 -  /* stats */
   3.732 -  OID_GEN_XMIT_OK,               // Q
   3.733 -  OID_GEN_RCV_OK,                // Q
   3.734 -  OID_GEN_XMIT_ERROR,            // Q
   3.735 -  OID_GEN_RCV_ERROR,             // Q
   3.736 -  OID_GEN_RCV_NO_BUFFER,         // Q
   3.737 -  /* media-specific OIDs */
   3.738 -  OID_802_3_PERMANENT_ADDRESS,
   3.739 -  OID_802_3_CURRENT_ADDRESS,
   3.740 -  OID_802_3_MULTICAST_LIST,
   3.741 -  OID_802_3_MAXIMUM_LIST_SIZE,
   3.742 -  /* tcp offload */
   3.743 -  OID_TCP_TASK_OFFLOAD,
   3.744 -};
   3.745 -
   3.746 -/* return 4 or 8 depending on size of buffer */
   3.747 -#define HANDLE_STAT_RETURN \
   3.748 -  {if (InformationBufferLength == 4) { \
   3.749 -    len = 4; *BytesNeeded = 8; \
   3.750 -    } else { \
   3.751 -    len = 8; \
   3.752 -    } }
   3.753 -
   3.754 -//#define OFFLOAD_LARGE_SEND
   3.755 -
   3.756 -NDIS_STATUS 
   3.757 -XenNet_QueryInformation(
   3.758 -  IN NDIS_HANDLE MiniportAdapterContext,
   3.759 -  IN NDIS_OID Oid,
   3.760 -  IN PVOID InformationBuffer,
   3.761 -  IN ULONG InformationBufferLength,
   3.762 -  OUT PULONG BytesWritten,
   3.763 -  OUT PULONG BytesNeeded)
   3.764 -{
   3.765 -  struct xennet_info *xi = MiniportAdapterContext;
   3.766 -  UCHAR vendor_desc[] = XN_VENDOR_DESC;
   3.767 -  ULONG64 temp_data;
   3.768 -  PVOID data = &temp_data;
   3.769 -  UINT len = 4;
   3.770 -  BOOLEAN used_temp_buffer = TRUE;
   3.771 -  NDIS_STATUS status = NDIS_STATUS_SUCCESS;
   3.772 -  PNDIS_TASK_OFFLOAD_HEADER ntoh;
   3.773 -  PNDIS_TASK_OFFLOAD nto;
   3.774 -  PNDIS_TASK_TCP_IP_CHECKSUM nttic;
   3.775 -#ifdef OFFLOAD_LARGE_SEND
   3.776 -  PNDIS_TASK_TCP_LARGE_SEND nttls;
   3.777 -#endif
   3.778 -
   3.779 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.780 -
   3.781 -  switch(Oid)
   3.782 -  {
   3.783 -    case OID_GEN_SUPPORTED_LIST:
   3.784 -      data = supported_oids;
   3.785 -      len = sizeof(supported_oids);
   3.786 -      break;
   3.787 -    case OID_GEN_HARDWARE_STATUS:
   3.788 -      if (!xi->connected)
   3.789 -        temp_data = NdisHardwareStatusInitializing;
   3.790 -      else
   3.791 -        temp_data = NdisHardwareStatusReady;
   3.792 -      break;
   3.793 -    case OID_GEN_MEDIA_SUPPORTED:
   3.794 -      temp_data = NdisMedium802_3;
   3.795 -      break;
   3.796 -    case OID_GEN_MEDIA_IN_USE:
   3.797 -      temp_data = NdisMedium802_3;
   3.798 -      break;
   3.799 -    case OID_GEN_MAXIMUM_LOOKAHEAD:
   3.800 -      temp_data = XN_DATA_SIZE;
   3.801 -      break;
   3.802 -    case OID_GEN_MAXIMUM_FRAME_SIZE:
   3.803 -      // According to the specs, OID_GEN_MAXIMUM_FRAME_SIZE does not include the header, so
   3.804 -      // it is XN_DATA_SIZE not XN_MAX_PKT_SIZE
   3.805 -      temp_data = XN_DATA_SIZE; // XN_MAX_PKT_SIZE;
   3.806 -      break;
   3.807 -    case OID_GEN_LINK_SPEED:
   3.808 -      temp_data = 10000000; /* 1Gb */
   3.809 -      break;
   3.810 -    case OID_GEN_TRANSMIT_BUFFER_SPACE:
   3.811 -      /* pkts times sizeof ring, maybe? */
   3.812 -      temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
   3.813 -      break;
   3.814 -    case OID_GEN_RECEIVE_BUFFER_SPACE:
   3.815 -      /* pkts times sizeof ring, maybe? */
   3.816 -      temp_data = XN_MAX_PKT_SIZE * NET_RX_RING_SIZE;
   3.817 -      break;
   3.818 -    case OID_GEN_TRANSMIT_BLOCK_SIZE:
   3.819 -      temp_data = XN_MAX_PKT_SIZE;
   3.820 -      break;
   3.821 -    case OID_GEN_RECEIVE_BLOCK_SIZE:
   3.822 -      temp_data = XN_MAX_PKT_SIZE;
   3.823 -      break;
   3.824 -    case OID_GEN_VENDOR_ID:
   3.825 -      temp_data = 0xFFFFFF; // Not guaranteed to be XENSOURCE_MAC_HDR;
   3.826 -      break;
   3.827 -    case OID_GEN_VENDOR_DESCRIPTION:
   3.828 -      data = vendor_desc;
   3.829 -      len = sizeof(vendor_desc);
   3.830 -      break;
   3.831 -    case OID_GEN_CURRENT_PACKET_FILTER:
   3.832 -      temp_data = xi->packet_filter;
   3.833 -      break;
   3.834 -    case OID_GEN_CURRENT_LOOKAHEAD:
   3.835 -      // TODO: we should store this...
   3.836 -      temp_data = XN_MAX_PKT_SIZE;
   3.837 -      break;
   3.838 -    case OID_GEN_DRIVER_VERSION:
   3.839 -      temp_data = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
   3.840 -      len = 2;
   3.841 -      break;
   3.842 -    case OID_GEN_MAXIMUM_TOTAL_SIZE:
   3.843 -      temp_data = XN_MAX_PKT_SIZE;
   3.844 -      break;
   3.845 -    case OID_GEN_MAC_OPTIONS:
   3.846 -      temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 
   3.847 -        NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
   3.848 -        NDIS_MAC_OPTION_NO_LOOPBACK;
   3.849 -      break;
   3.850 -    case OID_GEN_MEDIA_CONNECT_STATUS:
   3.851 -      if (xi->connected)
   3.852 -        temp_data = NdisMediaStateConnected;
   3.853 -      else
   3.854 -        temp_data = NdisMediaStateDisconnected;
   3.855 -      break;
   3.856 -    case OID_GEN_MAXIMUM_SEND_PACKETS:
   3.857 -      temp_data = XN_MAX_SEND_PKTS;
   3.858 -      break;
   3.859 -    case OID_GEN_XMIT_OK:
   3.860 -      temp_data = xi->stat_tx_ok;
   3.861 -      HANDLE_STAT_RETURN;
   3.862 -      break;
   3.863 -    case OID_GEN_RCV_OK:
   3.864 -      temp_data = xi->stat_rx_ok;
   3.865 -      HANDLE_STAT_RETURN;
   3.866 -      break;
   3.867 -    case OID_GEN_XMIT_ERROR:
   3.868 -      temp_data = xi->stat_tx_error;
   3.869 -      HANDLE_STAT_RETURN;
   3.870 -      break;
   3.871 -    case OID_GEN_RCV_ERROR:
   3.872 -      temp_data = xi->stat_rx_error;
   3.873 -      HANDLE_STAT_RETURN;
   3.874 -      break;
   3.875 -    case OID_GEN_RCV_NO_BUFFER:
   3.876 -      temp_data = xi->stat_rx_no_buffer;
   3.877 -      HANDLE_STAT_RETURN;
   3.878 -      break;
   3.879 -    case OID_802_3_PERMANENT_ADDRESS:
   3.880 -      data = xi->perm_mac_addr;
   3.881 -      len = ETH_ALEN;
   3.882 -      break;
   3.883 -    case OID_802_3_CURRENT_ADDRESS:
   3.884 -      data = xi->curr_mac_addr;
   3.885 -      len = ETH_ALEN;
   3.886 -      break;
   3.887 -    case OID_802_3_MULTICAST_LIST:
   3.888 -      data = NULL;
   3.889 -      len = 0;
   3.890 -    case OID_802_3_MAXIMUM_LIST_SIZE:
   3.891 -      temp_data = 0; /* no mcast support */
   3.892 -      break;
   3.893 -    case OID_TCP_TASK_OFFLOAD:
   3.894 -      KdPrint(("Get OID_TCP_TASK_OFFLOAD\n"));
   3.895 -      /* it's times like this that C really sucks */
   3.896 -
   3.897 -      len = sizeof(NDIS_TASK_OFFLOAD_HEADER);
   3.898 -
   3.899 -      len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   3.900 -        + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   3.901 -#ifdef OFFLOAD_LARGE_SEND
   3.902 -      len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   3.903 -        + sizeof(NDIS_TASK_TCP_LARGE_SEND);
   3.904 -#endif
   3.905 -
   3.906 -      if (len > InformationBufferLength)
   3.907 -      {
   3.908 -          break;
   3.909 -      }
   3.910 -
   3.911 -      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
   3.912 -      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
   3.913 -        || ntoh->Size != sizeof(*ntoh)
   3.914 -        || ntoh->EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation)
   3.915 -      {
   3.916 -        status = NDIS_STATUS_NOT_SUPPORTED;
   3.917 -        break;
   3.918 -      }
   3.919 -      ntoh->OffsetFirstTask = ntoh->Size;
   3.920 -
   3.921 -      /* fill in first nto */
   3.922 -      nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
   3.923 -      nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   3.924 -      nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   3.925 -      nto->Task = TcpIpChecksumNdisTask;
   3.926 -      nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   3.927 -
   3.928 -      /* fill in checksum offload struct */
   3.929 -      nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   3.930 -      nttic->V4Transmit.IpOptionsSupported = 0;
   3.931 -      nttic->V4Transmit.TcpOptionsSupported = 0;
   3.932 -      nttic->V4Transmit.TcpChecksum = 0;
   3.933 -      nttic->V4Transmit.UdpChecksum = 0;
   3.934 -      nttic->V4Transmit.IpChecksum = 0;
   3.935 -      nttic->V4Receive.IpOptionsSupported = 1;
   3.936 -      nttic->V4Receive.TcpOptionsSupported = 1;
   3.937 -      nttic->V4Receive.TcpChecksum = 1;
   3.938 -      nttic->V4Receive.UdpChecksum = 1;
   3.939 -      nttic->V4Receive.IpChecksum = 1;
   3.940 -      nttic->V6Transmit.IpOptionsSupported = 0;
   3.941 -      nttic->V6Transmit.TcpOptionsSupported = 0;
   3.942 -      nttic->V6Transmit.TcpChecksum = 0;
   3.943 -      nttic->V6Transmit.UdpChecksum = 0;
   3.944 -      nttic->V6Receive.IpOptionsSupported = 0;
   3.945 -      nttic->V6Receive.TcpOptionsSupported = 0;
   3.946 -      nttic->V6Receive.TcpChecksum = 0;
   3.947 -      nttic->V6Receive.UdpChecksum = 0;
   3.948 -
   3.949 -#ifdef OFFLOAD_LARGE_SEND
   3.950 -      /* offset from start of current NTO to start of next NTO */
   3.951 -      nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   3.952 -        + nto->TaskBufferLength;
   3.953 -
   3.954 -      /* fill in second nto */
   3.955 -      nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + nto->OffsetNextTask);
   3.956 -      nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   3.957 -      nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   3.958 -      nto->Task = TcpLargeSendNdisTask;
   3.959 -      nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
   3.960 -
   3.961 -      /* fill in large send struct */
   3.962 -      nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
   3.963 -      nttls->Version = 0;
   3.964 -      nttls->MaxOffLoadSize = 1024*64; /* made up, fixme */
   3.965 -      nttls->MinSegmentCount = 4; /* also made up */
   3.966 -      nttls->TcpOptions = FALSE;
   3.967 -      nttls->IpOptions = FALSE;
   3.968 -#endif
   3.969 -      nto->OffsetNextTask = 0; /* last one */
   3.970 -
   3.971 -      used_temp_buffer = FALSE;
   3.972 -      break;
   3.973 -    default:
   3.974 -      KdPrint(("Get Unknown OID 0x%x\n", Oid));
   3.975 -      status = NDIS_STATUS_NOT_SUPPORTED;
   3.976 -  }
   3.977 -
   3.978 -  if (!NT_SUCCESS(status))
   3.979 -  {
   3.980 -  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returned error)\n"));
   3.981 -    return status;
   3.982 -  }
   3.983 -
   3.984 -  if (len > InformationBufferLength)
   3.985 -  {
   3.986 -    *BytesNeeded = len;
   3.987 -    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (BUFFER_TOO_SHORT)\n"));
   3.988 -    return NDIS_STATUS_BUFFER_TOO_SHORT;
   3.989 -  }
   3.990 -
   3.991 -  *BytesWritten = len;
   3.992 -  if (len && used_temp_buffer)
   3.993 -  {
   3.994 -    NdisMoveMemory((PUCHAR)InformationBuffer, data, len);
   3.995 -  }
   3.996 -
   3.997 -  //KdPrint(("Got OID 0x%x\n", Oid));
   3.998 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.999 -
  3.1000 -  return status;
  3.1001 -}
  3.1002 -
  3.1003 -NDIS_STATUS 
  3.1004 -XenNet_SetInformation(
  3.1005 -  IN NDIS_HANDLE MiniportAdapterContext,
  3.1006 -  IN NDIS_OID Oid,
  3.1007 -  IN PVOID InformationBuffer,
  3.1008 -  IN ULONG InformationBufferLength,
  3.1009 -  OUT PULONG BytesRead,
  3.1010 -  OUT PULONG BytesNeeded
  3.1011 -  )
  3.1012 -{
  3.1013 -  NTSTATUS status;
  3.1014 -  struct xennet_info *xi = MiniportAdapterContext;
  3.1015 -  PULONG64 data = InformationBuffer;
  3.1016 -  PNDIS_TASK_OFFLOAD_HEADER ntoh;
  3.1017 -  PNDIS_TASK_OFFLOAD nto;
  3.1018 -  PNDIS_TASK_TCP_IP_CHECKSUM nttic;
  3.1019 -  int offset;
  3.1020 -
  3.1021 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
  3.1022 -
  3.1023 -  UNREFERENCED_PARAMETER(MiniportAdapterContext);
  3.1024 -  UNREFERENCED_PARAMETER(InformationBufferLength);
  3.1025 -  UNREFERENCED_PARAMETER(BytesRead);
  3.1026 -  UNREFERENCED_PARAMETER(BytesNeeded);
  3.1027 -
  3.1028 -  switch(Oid)
  3.1029 -  {
  3.1030 -    case OID_GEN_SUPPORTED_LIST:
  3.1031 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1032 -      KdPrint(("Unsupported set OID_GEN_SUPPORTED_LIST\n"));
  3.1033 -      break;
  3.1034 -    case OID_GEN_HARDWARE_STATUS:
  3.1035 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1036 -      KdPrint(("Unsupported set OID_GEN_HARDWARE_STATUS\n"));
  3.1037 -      break;
  3.1038 -    case OID_GEN_MEDIA_SUPPORTED:
  3.1039 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1040 -      KdPrint(("Unsupported set OID_GEN_MEDIA_SUPPORTED\n"));
  3.1041 -      break;
  3.1042 -    case OID_GEN_MEDIA_IN_USE:
  3.1043 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1044 -      KdPrint(("Unsupported set OID_GEN_MEDIA_IN_USE\n"));
  3.1045 -      break;
  3.1046 -    case OID_GEN_MAXIMUM_LOOKAHEAD:
  3.1047 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1048 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_LOOKAHEAD\n"));
  3.1049 -      break;
  3.1050 -    case OID_GEN_MAXIMUM_FRAME_SIZE:
  3.1051 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1052 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_FRAME_SIZE\n"));
  3.1053 -      break;
  3.1054 -    case OID_GEN_LINK_SPEED:
  3.1055 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1056 -      KdPrint(("Unsupported set OID_GEN_LINK_SPEED\n"));
  3.1057 -      break;
  3.1058 -    case OID_GEN_TRANSMIT_BUFFER_SPACE:
  3.1059 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1060 -      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
  3.1061 -      break;
  3.1062 -    case OID_GEN_RECEIVE_BUFFER_SPACE:
  3.1063 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1064 -      KdPrint(("Unsupported set OID_GEN_RECEIVE_BUFFER_SPACE\n"));
  3.1065 -      break;
  3.1066 -    case OID_GEN_TRANSMIT_BLOCK_SIZE:
  3.1067 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1068 -      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
  3.1069 -      break;
  3.1070 -    case OID_GEN_RECEIVE_BLOCK_SIZE:
  3.1071 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1072 -      KdPrint(("Unsupported set OID_GEN_RECEIVE_BLOCK_SIZE\n"));
  3.1073 -      break;
  3.1074 -    case OID_GEN_VENDOR_ID:
  3.1075 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1076 -      KdPrint(("Unsupported set OID_GEN_VENDOR_ID\n"));
  3.1077 -      break;
  3.1078 -    case OID_GEN_VENDOR_DESCRIPTION:
  3.1079 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1080 -      KdPrint(("Unsupported set OID_GEN_VENDOR_DESCRIPTION\n"));
  3.1081 -      break;
  3.1082 -    case OID_GEN_CURRENT_PACKET_FILTER:
  3.1083 -      KdPrint(("Set OID_GEN_CURRENT_PACKET_FILTER\n"));
  3.1084 -      xi->packet_filter = *(ULONG *)data;
  3.1085 -      status = NDIS_STATUS_SUCCESS;
  3.1086 -      break;
  3.1087 -    case OID_GEN_CURRENT_LOOKAHEAD:
  3.1088 -      KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d\n", *(int *)data));
  3.1089 -      // TODO: We should do this...
  3.1090 -      status = NDIS_STATUS_SUCCESS;
  3.1091 -      break;
  3.1092 -    case OID_GEN_DRIVER_VERSION:
  3.1093 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1094 -      KdPrint(("Unsupported set OID_GEN_DRIVER_VERSION\n"));
  3.1095 -      break;
  3.1096 -    case OID_GEN_MAXIMUM_TOTAL_SIZE:
  3.1097 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1098 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
  3.1099 -      break;
  3.1100 -    case OID_GEN_PROTOCOL_OPTIONS:
  3.1101 -      KdPrint(("Unsupported set OID_GEN_PROTOCOL_OPTIONS\n"));
  3.1102 -      // TODO - actually do this...
  3.1103 -      status = NDIS_STATUS_SUCCESS;
  3.1104 -      break;
  3.1105 -    case OID_GEN_MAC_OPTIONS:
  3.1106 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1107 -      KdPrint(("Unsupported set OID_GEN_MAC_OPTIONS\n"));
  3.1108 -      break;
  3.1109 -    case OID_GEN_MEDIA_CONNECT_STATUS:
  3.1110 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1111 -      KdPrint(("Unsupported set OID_GEN_MEDIA_CONNECT_STATUS\n"));
  3.1112 -      break;
  3.1113 -    case OID_GEN_MAXIMUM_SEND_PACKETS:
  3.1114 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1115 -      KdPrint(("Unsupported set OID_GEN_MAXIMUM_SEND_PACKETS\n"));
  3.1116 -      break;
  3.1117 -    case OID_GEN_XMIT_OK:
  3.1118 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1119 -      KdPrint(("Unsupported set OID_GEN_XMIT_OK\n"));
  3.1120 -      break;
  3.1121 -    case OID_GEN_RCV_OK:
  3.1122 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1123 -      KdPrint(("Unsupported set OID_GEN_RCV_OK\n"));
  3.1124 -      break;
  3.1125 -    case OID_GEN_XMIT_ERROR:
  3.1126 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1127 -      KdPrint(("Unsupported set OID_GEN_XMIT_ERROR\n"));
  3.1128 -      break;
  3.1129 -    case OID_GEN_RCV_ERROR:
  3.1130 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1131 -      KdPrint(("Unsupported set OID_GEN_RCV_ERROR\n"));
  3.1132 -      break;
  3.1133 -    case OID_GEN_RCV_NO_BUFFER:
  3.1134 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1135 -      KdPrint(("Unsupported set OID_GEN_RCV_NO_BUFFER\n"));
  3.1136 -      break;
  3.1137 -    case OID_802_3_PERMANENT_ADDRESS:
  3.1138 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1139 -      KdPrint(("Unsupported set OID_802_3_PERMANENT_ADDRESS\n"));
  3.1140 -      break;
  3.1141 -    case OID_802_3_CURRENT_ADDRESS:
  3.1142 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1143 -      KdPrint(("Unsupported set OID_802_3_CURRENT_ADDRESS\n"));
  3.1144 -      break;
  3.1145 -    case OID_802_3_MULTICAST_LIST:
  3.1146 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1147 -      KdPrint(("Unsupported set OID_802_3_MULTICAST_LIST\n"));
  3.1148 -      break;
  3.1149 -    case OID_802_3_MAXIMUM_LIST_SIZE:
  3.1150 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1151 -      KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
  3.1152 -      break;
  3.1153 -    case OID_TCP_TASK_OFFLOAD:
  3.1154 -      // Just fake this for now... ultimately we need to manually calc rx checksum if offload is disabled by windows
  3.1155 -      status = NDIS_STATUS_SUCCESS;
  3.1156 -      KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
  3.1157 -      // we should disable everything here, then enable what has been set
  3.1158 -      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
  3.1159 -      *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  3.1160 -      offset = ntoh->OffsetFirstTask;
  3.1161 -      nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
  3.1162 -      while (offset != 0)
  3.1163 -      {
  3.1164 -        *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
  3.1165 -        nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
  3.1166 -        switch (nto->Task)
  3.1167 -        {
  3.1168 -        case TcpIpChecksumNdisTask:
  3.1169 -          *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  3.1170 -          KdPrint(("TcpIpChecksumNdisTask\n"));
  3.1171 -          nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
  3.1172 -          KdPrint(("  V4Transmit.IpOptionsSupported  = %d\n", nttic->V4Transmit.IpOptionsSupported));
  3.1173 -          KdPrint(("  V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported));
  3.1174 -          KdPrint(("  V4Transmit.TcpChecksum         = %d\n", nttic->V4Transmit.TcpChecksum));
  3.1175 -          KdPrint(("  V4Transmit.UdpChecksum         = %d\n", nttic->V4Transmit.UdpChecksum));
  3.1176 -          KdPrint(("  V4Transmit.IpChecksum          = %d\n", nttic->V4Transmit.IpChecksum));
  3.1177 -          KdPrint(("  V4Receive.IpOptionsSupported   = %d\n", nttic->V4Receive.IpOptionsSupported));
  3.1178 -          KdPrint(("  V4Receive.TcpOptionsSupported  = %d\n", nttic->V4Receive.TcpOptionsSupported));
  3.1179 -          KdPrint(("  V4Receive.TcpChecksum          = %d\n", nttic->V4Receive.TcpChecksum));
  3.1180 -          KdPrint(("  V4Receive.UdpChecksum          = %d\n", nttic->V4Receive.UdpChecksum));
  3.1181 -          KdPrint(("  V4Receive.IpChecksum           = %d\n", nttic->V4Receive.IpChecksum));
  3.1182 -          KdPrint(("  V6Transmit.IpOptionsSupported  = %d\n", nttic->V6Transmit.IpOptionsSupported));
  3.1183 -          KdPrint(("  V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported));
  3.1184 -          KdPrint(("  V6Transmit.TcpChecksum         = %d\n", nttic->V6Transmit.TcpChecksum));
  3.1185 -          KdPrint(("  V6Transmit.UdpChecksum         = %d\n", nttic->V6Transmit.UdpChecksum));
  3.1186 -          KdPrint(("  V6Receive.IpOptionsSupported   = %d\n", nttic->V6Receive.IpOptionsSupported));
  3.1187 -          KdPrint(("  V6Receive.TcpOptionsSupported  = %d\n", nttic->V6Receive.TcpOptionsSupported));
  3.1188 -          KdPrint(("  V6Receive.TcpChecksum          = %d\n", nttic->V6Receive.TcpChecksum));
  3.1189 -          KdPrint(("  V6Receive.UdpChecksum          = %d\n", nttic->V6Receive.UdpChecksum));
  3.1190 -          break;
  3.1191 -        default:
  3.1192 -          KdPrint(("  Unknown Task %d\n", nto->Task));
  3.1193 -        }
  3.1194 -        offset = nto->OffsetNextTask;
  3.1195 -      }
  3.1196 -      break;
  3.1197 -    default:
  3.1198 -      KdPrint(("Set Unknown OID 0x%x\n", Oid));
  3.1199 -      status = NDIS_STATUS_NOT_SUPPORTED;
  3.1200 -      break;
  3.1201 -  }
  3.1202 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  3.1203 -  return status;
  3.1204 -}
  3.1205 -
  3.1206 -/* Called at DISPATCH_LEVEL with tx_lock held */
  3.1207 -static PMDL
  3.1208 -XenNet_Linearize(struct xennet_info *xi, PNDIS_PACKET Packet)
  3.1209 -{
  3.1210 -  PMDL pmdl;
  3.1211 -  char *start;
  3.1212 -  PNDIS_BUFFER buffer;
  3.1213 -  PVOID buff_va;
  3.1214 -  UINT buff_len;
  3.1215 -  UINT tot_buff_len;
  3.1216 -  LARGE_INTEGER tsc, dummy;
  3.1217 -
  3.1218 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
  3.1219 -
  3.1220 -  tsc = KeQueryPerformanceCounter(&dummy);
  3.1221 -
  3.1222 -  NdisGetFirstBufferFromPacketSafe(Packet, &buffer, &buff_va, &buff_len,
  3.1223 -    &tot_buff_len, NormalPagePriority);
  3.1224 -  ASSERT(tot_buff_len <= XN_MAX_PKT_SIZE);
  3.1225 -
  3.1226 -  pmdl = get_page_from_freelist(xi);
  3.1227 -  if (!pmdl)
  3.1228 -  {
  3.1229 -    KdPrint(("Could not allocate MDL for linearization\n"));
  3.1230 -    return NULL;
  3.1231 -  }
  3.1232 -
  3.1233 -  start = MmGetMdlVirtualAddress(pmdl);
  3.1234 -
  3.1235 -  while (buffer)
  3.1236 -  {
  3.1237 -    NdisQueryBufferSafe(buffer, &buff_va, &buff_len, NormalPagePriority);
  3.1238 -    RtlCopyMemory(start, buff_va, buff_len);
  3.1239 -    start += buff_len;
  3.1240 -    NdisGetNextBuffer(buffer, &buffer);
  3.1241 -  }
  3.1242 -
  3.1243 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  3.1244 -  ProfTime_Linearize.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
  3.1245 -  ProfCount_Linearize++;
  3.1246 -
  3.1247 -  return pmdl;
  3.1248 -}
  3.1249 -
  3.1250 -static VOID
  3.1251 -XenNet_SendQueuedPackets(struct xennet_info *xi)
  3.1252 -{
  3.1253 -  PLIST_ENTRY entry;
  3.1254 -  PNDIS_PACKET packet;
  3.1255 -  KIRQL OldIrql;
  3.1256 -  struct netif_tx_request *tx;
  3.1257 -  unsigned short id;
  3.1258 -  int notify;
  3.1259 -  PMDL pmdl;
  3.1260 -  UINT pkt_size;
  3.1261 -  LARGE_INTEGER tsc, dummy;
  3.1262 -  KIRQL OldIrql2;
  3.1263 -//  LARGE_INTEGER gtsc;
  3.1264 -
  3.1265 -  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql2);
  3.1266 -
  3.1267 -  tsc = KeQueryPerformanceCounter(&dummy);
  3.1268 -  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
  3.1269 -
  3.1270 -  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
  3.1271 -  /* if empty, the above returns head*, not NULL */
  3.1272 -  while (entry != &xi->tx_waiting_pkt_list)
  3.1273 -  {
  3.1274 -    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
  3.1275 -
  3.1276 -    NdisQueryPacket(packet, NULL, NULL, NULL, &pkt_size);
  3.1277 -    pmdl = *(PMDL *)packet->MiniportReservedEx;
  3.1278 -
  3.1279 -    id = get_id_from_freelist(xi);
  3.1280 -    if (!id)
  3.1281 -    {
  3.1282 -      /* whups, out of space on the ring. requeue and get out */
  3.1283 -      InsertHeadList(&xi->tx_waiting_pkt_list, entry);
  3.1284 -      break;
  3.1285 -    }
  3.1286 -    xi->tx_pkts[id] = packet;
  3.1287 -
  3.1288 -    tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
  3.1289 -    tx->id = id;
  3.1290 -    tx->gref = get_grant_ref(pmdl);
  3.1291 -/*
  3.1292 -gtsc = KeQueryPerformanceCounter(&dummy);
  3.1293 -    tx->gref = xi->XenInterface.GntTbl_GrantAccess(
  3.1294 -      xi->XenInterface.InterfaceHeader.Context,
  3.1295 -      0,
  3.1296 -      *MmGetMdlPfnArray(pmdl),
  3.1297 -      TRUE);
  3.1298 -ProfTime_GrantAccess.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - gtsc.QuadPart;
  3.1299 -ProfCount_GrantAccess++;
  3.1300 -*/
  3.1301 -    xi->grant_tx_ref[id] = tx->gref;
  3.1302 -    tx->offset = (uint16_t)MmGetMdlByteOffset(pmdl);
  3.1303 -    tx->size = (UINT16)pkt_size;
  3.1304 -    // NETTXF_csum_blank should only be used for tcp and udp packets...    
  3.1305 -    tx->flags = 0; //NETTXF_csum_blank;
  3.1306 -
  3.1307 -    xi->tx.req_prod_pvt++;
  3.1308 -
  3.1309 -    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
  3.1310 -  }
  3.1311 -
  3.1312 -  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->tx, notify);
  3.1313 -  if (notify)
  3.1314 -  {
  3.1315 -    xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
  3.1316 -      xi->event_channel);
  3.1317 -  }
  3.1318 -
  3.1319 -  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
  3.1320 -  ProfTime_SendQueuedPackets.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
  3.1321 -  ProfCount_SendQueuedPackets++;
  3.1322 -
  3.1323 -  KeLowerIrql(OldIrql2);
  3.1324 -}
  3.1325 -
  3.1326 -VOID
  3.1327 -XenNet_SendPackets(
  3.1328 -  IN NDIS_HANDLE MiniportAdapterContext,
  3.1329 -  IN PPNDIS_PACKET PacketArray,
  3.1330 -  IN UINT NumberOfPackets
  3.1331 -  )
  3.1332 -{
  3.1333 -  struct xennet_info *xi = MiniportAdapterContext;
  3.1334 -  PNDIS_PACKET curr_packet;
  3.1335 -  UINT i;
  3.1336 -  PMDL pmdl;
  3.1337 -  PLIST_ENTRY entry;
  3.1338 -  KIRQL OldIrql;
  3.1339 -  LARGE_INTEGER tsc, dummy;
  3.1340 -  KIRQL OldIrql2;
  3.1341 -
  3.1342 -  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql2);
  3.1343 -  tsc = KeQueryPerformanceCounter(&dummy);
  3.1344 -
  3.1345 -  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
  3.1346 -
  3.1347 -  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
  3.1348 -  for (i = 0; i < NumberOfPackets; i++)
  3.1349 -  {
  3.1350 -    curr_packet = PacketArray[i];
  3.1351 -    ASSERT(curr_packet);
  3.1352 -
  3.1353 -    //KdPrint(("sending pkt, len %d\n", pkt_size));
  3.1354 -
  3.1355 -    pmdl = XenNet_Linearize(xi, curr_packet);
  3.1356 -    if (!pmdl)
  3.1357 -    {
  3.1358 -      KdPrint((__DRIVER_NAME "Couldn't linearize packet!\n"));
  3.1359 -      NdisMSendComplete(xi->adapter_handle, curr_packet, NDIS_STATUS_FAILURE);
  3.1360 -      break;
  3.1361 -    }
  3.1362 -
  3.1363 -    /* NOTE: 
  3.1364 -     * We use the UCHAR[3*sizeof(PVOID)] array in each packet's MiniportReservedEx thusly:
  3.1365 -     * 0: PMDL to linearized data
  3.1366 -     * sizeof(PVOID)+: LIST_ENTRY for placing packet on the waiting pkt list
  3.1367 -     */
  3.1368 -    *(PMDL *)&curr_packet->MiniportReservedEx = pmdl;
  3.1369 -
  3.1370 -    entry = (PLIST_ENTRY)&curr_packet->MiniportReservedEx[sizeof(PVOID)];
  3.1371 -    InsertTailList(&xi->tx_waiting_pkt_list, entry);
  3.1372 -    InterlockedIncrement(&xi->tx_outstanding);
  3.1373 -  }
  3.1374 -  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
  3.1375 -
  3.1376 -  ProfTime_SendPackets.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
  3.1377 -  ProfCount_SendPackets++;
  3.1378 -  KeLowerIrql(OldIrql2);
  3.1379 -  XenNet_SendQueuedPackets(xi);
  3.1380 -
  3.1381 -  if ((ProfCount_SendPackets & 1023) == 0)
  3.1382 -  {
  3.1383 -    KdPrint((__DRIVER_NAME "     TxBufferGC        Count = %10d, Avg Time = %10ld\n", ProfCount_TxBufferGC, (ProfCount_TxBufferGC == 0)?0:(ProfTime_TxBufferGC.QuadPart / ProfCount_TxBufferGC)));
  3.1384 -    KdPrint((__DRIVER_NAME "     TxBufferFree      Count = %10d, Avg Time = %10ld\n", ProfCount_TxBufferFree, (ProfCount_TxBufferFree == 0)?0:(ProfTime_TxBufferFree.QuadPart / ProfCount_TxBufferFree)));
  3.1385 -    KdPrint((__DRIVER_NAME "     RxBufferAlloc     Count = %10d, Avg Time = %10ld\n", ProfCount_RxBufferAlloc, (ProfCount_RxBufferAlloc == 0)?0:(ProfTime_RxBufferAlloc.QuadPart / ProfCount_RxBufferAlloc)));
  3.1386 -    KdPrint((__DRIVER_NAME "     RxBufferFree      Count = %10d, Avg Time = %10ld\n", ProfCount_RxBufferFree, (ProfCount_RxBufferFree == 0)?0:(ProfTime_RxBufferFree.QuadPart / ProfCount_RxBufferFree)));
  3.1387 -    KdPrint((__DRIVER_NAME "     ReturnPacket      Count = %10d, Avg Time = %10ld\n", ProfCount_ReturnPacket, (ProfCount_ReturnPacket == 0)?0:(ProfTime_ReturnPacket.QuadPart / ProfCount_ReturnPacket)));
  3.1388 -    KdPrint((__DRIVER_NAME "     RxBufferCheck     Count = %10d, Avg Time = %10ld\n", ProfCount_RxBufferCheck, (ProfCount_RxBufferCheck == 0)?0:(ProfTime_RxBufferCheck.QuadPart / ProfCount_RxBufferCheck)));
  3.1389 -    KdPrint((__DRIVER_NAME "     Linearize         Count = %10d, Avg Time = %10ld\n", ProfCount_Linearize, (ProfCount_Linearize == 0)?0:(ProfTime_Linearize.QuadPart / ProfCount_Linearize)));
  3.1390 -    KdPrint((__DRIVER_NAME "     SendPackets       Count = %10d, Avg Time = %10ld\n", ProfCount_SendPackets, (ProfCount_SendPackets == 0)?0:(ProfTime_SendPackets.QuadPart / ProfCount_SendPackets)));
  3.1391 -    KdPrint((__DRIVER_NAME "     SendQueuedPackets Count = %10d, Avg Time = %10ld\n", ProfCount_SendQueuedPackets, (ProfCount_SendQueuedPackets == 0)?0:(ProfTime_SendQueuedPackets.QuadPart / ProfCount_SendQueuedPackets)));
  3.1392 -    KdPrint((__DRIVER_NAME "     GrantAccess       Count = %10d, Avg Time = %10ld\n", ProfCount_GrantAccess, (ProfCount_GrantAccess == 0)?0:(ProfTime_GrantAccess.QuadPart / ProfCount_GrantAccess)));
  3.1393 -    KdPrint((__DRIVER_NAME "     EndAccess         Count = %10d, Avg Time = %10ld\n", ProfCount_EndAccess, (ProfCount_EndAccess == 0)?0:(ProfTime_EndAccess.QuadPart / ProfCount_EndAccess)));
  3.1394 -  }
  3.1395 -  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  3.1396 -}
  3.1397 -
  3.1398  VOID
  3.1399  XenNet_PnPEventNotify(
  3.1400    IN NDIS_HANDLE MiniportAdapterContext,
  3.1401 @@ -1863,8 +617,10 @@ XenNet_Halt(
  3.1402    }
  3.1403    xi->rx_pgs = NULL;
  3.1404  
  3.1405 -  XenNet_TxBufferFree(xi);
  3.1406 -  XenNet_RxBufferFree(MiniportAdapterContext);
  3.1407 +  XenNet_TxShutdown(xi);
  3.1408 +  XenNet_RxShutdown(xi);
  3.1409 +
  3.1410 +  free_page_freelist(xi);
  3.1411  
  3.1412    /* Remove watch on backend state */
  3.1413    RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->backend_path);
     4.1 --- a/xennet/xennet.h	Sat Mar 01 00:40:44 2008 +1100
     4.2 +++ b/xennet/xennet.h	Sun Mar 02 16:54:23 2008 +1100
     4.3 @@ -47,12 +47,31 @@ Foundation, Inc., 51 Franklin Street, Fi
     4.4  #include <xen_public.h>
     4.5  #include <io/ring.h>
     4.6  #include <io/netif.h>
     4.7 +#include <io/xenbus.h>
     4.8 +#include <stdlib.h>
     4.9  #define XENNET_POOL_TAG (ULONG) 'XenN'
    4.10  
    4.11 +/* Xen macros use these, so they need to be redefined to Win equivs */
    4.12 +#define wmb() KeMemoryBarrier()
    4.13 +#define mb() KeMemoryBarrier()
    4.14 +
    4.15 +#define GRANT_INVALID_REF 0
    4.16 +
    4.17  #define NAME_SIZE 64
    4.18  
    4.19  #define ETH_ALEN 6
    4.20  
    4.21 +/* couldn't get regular xen ring macros to work...*/
    4.22 +#define __NET_RING_SIZE(type, _sz) \
    4.23 +    (__RD32( \
    4.24 +    (_sz - sizeof(struct type##_sring) + sizeof(union type##_sring_entry)) \
    4.25 +    / sizeof(union type##_sring_entry)))
    4.26 +
    4.27 +#define NET_TX_RING_SIZE __NET_RING_SIZE(netif_tx, PAGE_SIZE)
    4.28 +#define NET_RX_RING_SIZE __NET_RING_SIZE(netif_rx, PAGE_SIZE)
    4.29 +
    4.30 +#pragma warning(disable: 4127) // conditional expression is constant
    4.31 +
    4.32  /* TODO: crank this up if we support higher mtus? */
    4.33  #define XN_DATA_SIZE 1500
    4.34  #define XN_HDR_SIZE 14
    4.35 @@ -64,4 +83,167 @@ Foundation, Inc., 51 Franklin Street, Fi
    4.36  #define XN_RX_QUEUE_LEN 256
    4.37  #define XENSOURCE_MAC_HDR 0x00163E
    4.38  #define XN_VENDOR_DESC "Xensource"
    4.39 -#define MAX_XENBUS_STR_LEN 128
    4.40 \ No newline at end of file
    4.41 +#define MAX_XENBUS_STR_LEN 128
    4.42 +
    4.43 +struct xennet_info
    4.44 +{
    4.45 +  /* Base device vars */
    4.46 +  PDEVICE_OBJECT pdo;
    4.47 +  PDEVICE_OBJECT fdo;
    4.48 +  PDEVICE_OBJECT lower_do;
    4.49 +  WDFDEVICE wdf_device;
    4.50 +  WCHAR dev_desc[NAME_SIZE];
    4.51 +
    4.52 +  /* NDIS-related vars */
    4.53 +  NDIS_HANDLE adapter_handle;
    4.54 +  NDIS_HANDLE packet_pool;
    4.55 +  NDIS_HANDLE buffer_pool;
    4.56 +  ULONG packet_filter;
    4.57 +  int connected;
    4.58 +  UINT8 perm_mac_addr[ETH_ALEN];
    4.59 +  UINT8 curr_mac_addr[ETH_ALEN];
    4.60 +
    4.61 +  /* Misc. Xen vars */
    4.62 +  XEN_IFACE XenInterface;
    4.63 +  PXENPCI_XEN_DEVICE_DATA pdo_data;
    4.64 +  evtchn_port_t event_channel;
    4.65 +  ULONG state;
    4.66 +  KEVENT backend_state_change_event;
    4.67 +  KEVENT shutdown_event;
    4.68 +  char backend_path[MAX_XENBUS_STR_LEN];
    4.69 +  ULONG backend_state;
    4.70 +
    4.71 +  /* Xen ring-related vars */
    4.72 +  KSPIN_LOCK rx_lock;
    4.73 +
    4.74 +  /* tx related - protected by tx_lock */
    4.75 +  KSPIN_LOCK tx_lock;
    4.76 +  LIST_ENTRY tx_waiting_pkt_list;
    4.77 +  struct netif_tx_front_ring tx;
    4.78 +  grant_ref_t tx_ring_ref;
    4.79 +  struct netif_tx_sring *tx_pgs;
    4.80 +  PMDL tx_mdl;
    4.81 +  USHORT tx_id_list[NET_TX_RING_SIZE];
    4.82 +  ULONG tx_id_free;
    4.83 +  PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE];
    4.84 +
    4.85 +  /* rx_related - protected by rx_lock */
    4.86 +  struct netif_rx_front_ring rx;
    4.87 +  grant_ref_t rx_ring_ref;
    4.88 +  struct netif_rx_sring *rx_pgs;
    4.89 +  PMDL rx_mdl;
    4.90 +  USHORT rx_id_list[NET_RX_RING_SIZE];
    4.91 +  ULONG rx_id_free;
    4.92 +  PNDIS_BUFFER rx_buffers[NET_RX_RING_SIZE];
    4.93 +
    4.94 +  /* id list - protected by page_lock */
    4.95 +  PMDL page_list[NET_TX_RING_SIZE + NET_RX_RING_SIZE];
    4.96 +  ULONG page_free;
    4.97 +  KSPIN_LOCK page_lock;
    4.98 +
    4.99 +  /* Receive-ring batched refills. */
   4.100 +#define RX_MIN_TARGET 8
   4.101 +#define RX_DFL_MIN_TARGET 64
   4.102 +#define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
   4.103 +  ULONG rx_target;
   4.104 +  ULONG rx_max_target;
   4.105 +  ULONG rx_min_target;
   4.106 +
   4.107 +  /* how many packets are in the net stack atm */
   4.108 +  LONG rx_outstanding;
   4.109 +  LONG tx_outstanding;
   4.110 +
   4.111 +  /* stats */
   4.112 +  ULONG64 stat_tx_ok;
   4.113 +  ULONG64 stat_rx_ok;
   4.114 +  ULONG64 stat_tx_error;
   4.115 +  ULONG64 stat_rx_error;
   4.116 +  ULONG64 stat_rx_no_buffer;
   4.117 +} typedef xennet_info_t;
   4.118 +
   4.119 +
   4.120 +extern LARGE_INTEGER ProfTime_TxBufferGC;
   4.121 +extern LARGE_INTEGER ProfTime_TxBufferFree;
   4.122 +extern LARGE_INTEGER ProfTime_RxBufferAlloc;
   4.123 +extern LARGE_INTEGER ProfTime_RxBufferFree;
   4.124 +extern LARGE_INTEGER ProfTime_ReturnPacket;
   4.125 +extern LARGE_INTEGER ProfTime_RxBufferCheck;
   4.126 +extern LARGE_INTEGER ProfTime_Linearize;
   4.127 +extern LARGE_INTEGER ProfTime_SendPackets;
   4.128 +extern LARGE_INTEGER ProfTime_SendQueuedPackets;
   4.129 +extern LARGE_INTEGER ProfTime_GrantAccess;
   4.130 +extern LARGE_INTEGER ProfTime_EndAccess;
   4.131 +
   4.132 +extern int ProfCount_TxBufferGC;
   4.133 +extern int ProfCount_TxBufferFree;
   4.134 +extern int ProfCount_RxBufferAlloc;
   4.135 +extern int ProfCount_RxBufferFree;
   4.136 +extern int ProfCount_ReturnPacket;
   4.137 +extern int ProfCount_RxBufferCheck;
   4.138 +extern int ProfCount_Linearize;
   4.139 +extern int ProfCount_SendPackets;
   4.140 +extern int ProfCount_SendQueuedPackets;
   4.141 +extern int ProfCount_GrantAccess;
   4.142 +extern int ProfCount_EndAccess;
   4.143 +
   4.144 +NDIS_STATUS
   4.145 +XenNet_RxBufferCheck(struct xennet_info *xi);
   4.146 +
   4.147 +VOID
   4.148 +XenNet_ReturnPacket(
   4.149 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.150 +  IN PNDIS_PACKET Packet
   4.151 +  );
   4.152 +
   4.153 +BOOLEAN
   4.154 +XenNet_RxInit(xennet_info_t *xi);
   4.155 +
   4.156 +BOOLEAN
   4.157 +XenNet_RxShutdown(xennet_info_t *xi);
   4.158 +
   4.159 +NDIS_STATUS
   4.160 +XenNet_TxBufferGC(struct xennet_info *xi);
   4.161 +
   4.162 +VOID
   4.163 +XenNet_SendPackets(
   4.164 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.165 +  IN PPNDIS_PACKET PacketArray,
   4.166 +  IN UINT NumberOfPackets
   4.167 +  );
   4.168 +
   4.169 +BOOLEAN
   4.170 +XenNet_TxInit(xennet_info_t *xi);
   4.171 +
   4.172 +BOOLEAN
   4.173 +XenNet_TxShutdown(xennet_info_t *xi);
   4.174 +
   4.175 +NDIS_STATUS 
   4.176 +XenNet_QueryInformation(
   4.177 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.178 +  IN NDIS_OID Oid,
   4.179 +  IN PVOID InformationBuffer,
   4.180 +  IN ULONG InformationBufferLength,
   4.181 +  OUT PULONG BytesWritten,
   4.182 +  OUT PULONG BytesNeeded);
   4.183 +
   4.184 +NDIS_STATUS 
   4.185 +XenNet_SetInformation(
   4.186 +  IN NDIS_HANDLE MiniportAdapterContext,
   4.187 +  IN NDIS_OID Oid,
   4.188 +  IN PVOID InformationBuffer,
   4.189 +  IN ULONG InformationBufferLength,
   4.190 +  OUT PULONG BytesRead,
   4.191 +  OUT PULONG BytesNeeded
   4.192 +  );
   4.193 +
   4.194 +static __inline grant_ref_t
   4.195 +get_grant_ref(PMDL mdl)
   4.196 +{
   4.197 +  return *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE));
   4.198 +}
   4.199 +
   4.200 +VOID
   4.201 +put_page_on_freelist(struct xennet_info *xi, PMDL mdl);
   4.202 +
   4.203 +PMDL
   4.204 +get_page_from_freelist(struct xennet_info *xi);
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xennet/xennet_oid.c	Sun Mar 02 16:54:23 2008 +1100
     5.3 @@ -0,0 +1,521 @@
     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 "xennet.h"
    5.25 +
    5.26 +// Q = Query Mandatory, S = Set Mandatory
    5.27 +NDIS_OID supported_oids[] =
    5.28 +{
    5.29 +  /* general OIDs */
    5.30 +  OID_GEN_SUPPORTED_LIST,        // Q
    5.31 +  OID_GEN_HARDWARE_STATUS,       // Q
    5.32 +  OID_GEN_MEDIA_SUPPORTED,       // Q
    5.33 +  OID_GEN_MEDIA_IN_USE,          // Q
    5.34 +  OID_GEN_MAXIMUM_LOOKAHEAD,     // Q
    5.35 +  OID_GEN_MAXIMUM_FRAME_SIZE,    // Q
    5.36 +  OID_GEN_LINK_SPEED,            // Q
    5.37 +  OID_GEN_TRANSMIT_BUFFER_SPACE, // Q
    5.38 +  OID_GEN_RECEIVE_BUFFER_SPACE,  // Q
    5.39 +  OID_GEN_TRANSMIT_BLOCK_SIZE,   // Q
    5.40 +  OID_GEN_RECEIVE_BLOCK_SIZE,    // Q
    5.41 +  OID_GEN_VENDOR_ID,             // Q
    5.42 +  OID_GEN_VENDOR_DESCRIPTION,    // Q
    5.43 +  OID_GEN_CURRENT_PACKET_FILTER, // QS
    5.44 +  OID_GEN_CURRENT_LOOKAHEAD,     // QS
    5.45 +  OID_GEN_DRIVER_VERSION,        // Q
    5.46 +  OID_GEN_MAXIMUM_TOTAL_SIZE,    // Q
    5.47 +  OID_GEN_PROTOCOL_OPTIONS,      // S
    5.48 +  OID_GEN_MAC_OPTIONS,           // Q
    5.49 +  OID_GEN_MEDIA_CONNECT_STATUS,  // Q
    5.50 +  OID_GEN_MAXIMUM_SEND_PACKETS,  // Q
    5.51 +  /* stats */
    5.52 +  OID_GEN_XMIT_OK,               // Q
    5.53 +  OID_GEN_RCV_OK,                // Q
    5.54 +  OID_GEN_XMIT_ERROR,            // Q
    5.55 +  OID_GEN_RCV_ERROR,             // Q
    5.56 +  OID_GEN_RCV_NO_BUFFER,         // Q
    5.57 +  /* media-specific OIDs */
    5.58 +  OID_802_3_PERMANENT_ADDRESS,
    5.59 +  OID_802_3_CURRENT_ADDRESS,
    5.60 +  OID_802_3_MULTICAST_LIST,
    5.61 +  OID_802_3_MAXIMUM_LIST_SIZE,
    5.62 +  /* tcp offload */
    5.63 +  OID_TCP_TASK_OFFLOAD,
    5.64 +};
    5.65 +
    5.66 +/* return 4 or 8 depending on size of buffer */
    5.67 +#define HANDLE_STAT_RETURN \
    5.68 +  {if (InformationBufferLength == 4) { \
    5.69 +    len = 4; *BytesNeeded = 8; \
    5.70 +    } else { \
    5.71 +    len = 8; \
    5.72 +    } }
    5.73 +
    5.74 +//#define OFFLOAD_LARGE_SEND
    5.75 +
    5.76 +NDIS_STATUS 
    5.77 +XenNet_QueryInformation(
    5.78 +  IN NDIS_HANDLE MiniportAdapterContext,
    5.79 +  IN NDIS_OID Oid,
    5.80 +  IN PVOID InformationBuffer,
    5.81 +  IN ULONG InformationBufferLength,
    5.82 +  OUT PULONG BytesWritten,
    5.83 +  OUT PULONG BytesNeeded)
    5.84 +{
    5.85 +  struct xennet_info *xi = MiniportAdapterContext;
    5.86 +  UCHAR vendor_desc[] = XN_VENDOR_DESC;
    5.87 +  ULONG64 temp_data;
    5.88 +  PVOID data = &temp_data;
    5.89 +  UINT len = 4;
    5.90 +  BOOLEAN used_temp_buffer = TRUE;
    5.91 +  NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    5.92 +  PNDIS_TASK_OFFLOAD_HEADER ntoh;
    5.93 +  PNDIS_TASK_OFFLOAD nto;
    5.94 +  PNDIS_TASK_TCP_IP_CHECKSUM nttic;
    5.95 +#ifdef OFFLOAD_LARGE_SEND
    5.96 +  PNDIS_TASK_TCP_LARGE_SEND nttls;
    5.97 +#endif
    5.98 +
    5.99 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.100 +
   5.101 +  switch(Oid)
   5.102 +  {
   5.103 +    case OID_GEN_SUPPORTED_LIST:
   5.104 +      data = supported_oids;
   5.105 +      len = sizeof(supported_oids);
   5.106 +      break;
   5.107 +    case OID_GEN_HARDWARE_STATUS:
   5.108 +      if (!xi->connected)
   5.109 +        temp_data = NdisHardwareStatusInitializing;
   5.110 +      else
   5.111 +        temp_data = NdisHardwareStatusReady;
   5.112 +      break;
   5.113 +    case OID_GEN_MEDIA_SUPPORTED:
   5.114 +      temp_data = NdisMedium802_3;
   5.115 +      break;
   5.116 +    case OID_GEN_MEDIA_IN_USE:
   5.117 +      temp_data = NdisMedium802_3;
   5.118 +      break;
   5.119 +    case OID_GEN_MAXIMUM_LOOKAHEAD:
   5.120 +      temp_data = XN_DATA_SIZE;
   5.121 +      break;
   5.122 +    case OID_GEN_MAXIMUM_FRAME_SIZE:
   5.123 +      // According to the specs, OID_GEN_MAXIMUM_FRAME_SIZE does not include the header, so
   5.124 +      // it is XN_DATA_SIZE not XN_MAX_PKT_SIZE
   5.125 +      temp_data = XN_DATA_SIZE; // XN_MAX_PKT_SIZE;
   5.126 +      break;
   5.127 +    case OID_GEN_LINK_SPEED:
   5.128 +      temp_data = 10000000; /* 1Gb */
   5.129 +      break;
   5.130 +    case OID_GEN_TRANSMIT_BUFFER_SPACE:
   5.131 +      /* pkts times sizeof ring, maybe? */
   5.132 +      temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
   5.133 +      break;
   5.134 +    case OID_GEN_RECEIVE_BUFFER_SPACE:
   5.135 +      /* pkts times sizeof ring, maybe? */
   5.136 +      temp_data = XN_MAX_PKT_SIZE * NET_RX_RING_SIZE;
   5.137 +      break;
   5.138 +    case OID_GEN_TRANSMIT_BLOCK_SIZE:
   5.139 +      temp_data = XN_MAX_PKT_SIZE;
   5.140 +      break;
   5.141 +    case OID_GEN_RECEIVE_BLOCK_SIZE:
   5.142 +      temp_data = XN_MAX_PKT_SIZE;
   5.143 +      break;
   5.144 +    case OID_GEN_VENDOR_ID:
   5.145 +      temp_data = 0xFFFFFF; // Not guaranteed to be XENSOURCE_MAC_HDR;
   5.146 +      break;
   5.147 +    case OID_GEN_VENDOR_DESCRIPTION:
   5.148 +      data = vendor_desc;
   5.149 +      len = sizeof(vendor_desc);
   5.150 +      break;
   5.151 +    case OID_GEN_CURRENT_PACKET_FILTER:
   5.152 +      temp_data = xi->packet_filter;
   5.153 +      break;
   5.154 +    case OID_GEN_CURRENT_LOOKAHEAD:
   5.155 +      // TODO: we should store this...
   5.156 +      temp_data = XN_MAX_PKT_SIZE;
   5.157 +      break;
   5.158 +    case OID_GEN_DRIVER_VERSION:
   5.159 +      temp_data = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
   5.160 +      len = 2;
   5.161 +      break;
   5.162 +    case OID_GEN_MAXIMUM_TOTAL_SIZE:
   5.163 +      temp_data = XN_MAX_PKT_SIZE;
   5.164 +      break;
   5.165 +    case OID_GEN_MAC_OPTIONS:
   5.166 +      temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 
   5.167 +        NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
   5.168 +        NDIS_MAC_OPTION_NO_LOOPBACK;
   5.169 +      break;
   5.170 +    case OID_GEN_MEDIA_CONNECT_STATUS:
   5.171 +      if (xi->connected)
   5.172 +        temp_data = NdisMediaStateConnected;
   5.173 +      else
   5.174 +        temp_data = NdisMediaStateDisconnected;
   5.175 +      break;
   5.176 +    case OID_GEN_MAXIMUM_SEND_PACKETS:
   5.177 +      temp_data = XN_MAX_SEND_PKTS;
   5.178 +      break;
   5.179 +    case OID_GEN_XMIT_OK:
   5.180 +      temp_data = xi->stat_tx_ok;
   5.181 +      HANDLE_STAT_RETURN;
   5.182 +      break;
   5.183 +    case OID_GEN_RCV_OK:
   5.184 +      temp_data = xi->stat_rx_ok;
   5.185 +      HANDLE_STAT_RETURN;
   5.186 +      break;
   5.187 +    case OID_GEN_XMIT_ERROR:
   5.188 +      temp_data = xi->stat_tx_error;
   5.189 +      HANDLE_STAT_RETURN;
   5.190 +      break;
   5.191 +    case OID_GEN_RCV_ERROR:
   5.192 +      temp_data = xi->stat_rx_error;
   5.193 +      HANDLE_STAT_RETURN;
   5.194 +      break;
   5.195 +    case OID_GEN_RCV_NO_BUFFER:
   5.196 +      temp_data = xi->stat_rx_no_buffer;
   5.197 +      HANDLE_STAT_RETURN;
   5.198 +      break;
   5.199 +    case OID_802_3_PERMANENT_ADDRESS:
   5.200 +      data = xi->perm_mac_addr;
   5.201 +      len = ETH_ALEN;
   5.202 +      break;
   5.203 +    case OID_802_3_CURRENT_ADDRESS:
   5.204 +      data = xi->curr_mac_addr;
   5.205 +      len = ETH_ALEN;
   5.206 +      break;
   5.207 +    case OID_802_3_MULTICAST_LIST:
   5.208 +      data = NULL;
   5.209 +      len = 0;
   5.210 +    case OID_802_3_MAXIMUM_LIST_SIZE:
   5.211 +      temp_data = 0; /* no mcast support */
   5.212 +      break;
   5.213 +    case OID_TCP_TASK_OFFLOAD:
   5.214 +      KdPrint(("Get OID_TCP_TASK_OFFLOAD\n"));
   5.215 +      /* it's times like this that C really sucks */
   5.216 +
   5.217 +      len = sizeof(NDIS_TASK_OFFLOAD_HEADER);
   5.218 +
   5.219 +      len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   5.220 +        + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   5.221 +#ifdef OFFLOAD_LARGE_SEND
   5.222 +      len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   5.223 +        + sizeof(NDIS_TASK_TCP_LARGE_SEND);
   5.224 +#endif
   5.225 +
   5.226 +      if (len > InformationBufferLength)
   5.227 +      {
   5.228 +          break;
   5.229 +      }
   5.230 +
   5.231 +      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
   5.232 +      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
   5.233 +        || ntoh->Size != sizeof(*ntoh)
   5.234 +        || ntoh->EncapsulationFormat.Encapsulation != IEEE_802_3_Encapsulation)
   5.235 +      {
   5.236 +        status = NDIS_STATUS_NOT_SUPPORTED;
   5.237 +        break;
   5.238 +      }
   5.239 +      ntoh->OffsetFirstTask = ntoh->Size;
   5.240 +
   5.241 +      /* fill in first nto */
   5.242 +      nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
   5.243 +      nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   5.244 +      nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   5.245 +      nto->Task = TcpIpChecksumNdisTask;
   5.246 +      nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   5.247 +
   5.248 +      /* fill in checksum offload struct */
   5.249 +      nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   5.250 +      nttic->V4Transmit.IpOptionsSupported = 0;
   5.251 +      nttic->V4Transmit.TcpOptionsSupported = 0;
   5.252 +      nttic->V4Transmit.TcpChecksum = 0;
   5.253 +      nttic->V4Transmit.UdpChecksum = 0;
   5.254 +      nttic->V4Transmit.IpChecksum = 0;
   5.255 +      nttic->V4Receive.IpOptionsSupported = 1;
   5.256 +      nttic->V4Receive.TcpOptionsSupported = 1;
   5.257 +      nttic->V4Receive.TcpChecksum = 1;
   5.258 +      nttic->V4Receive.UdpChecksum = 1;
   5.259 +      nttic->V4Receive.IpChecksum = 1;
   5.260 +      nttic->V6Transmit.IpOptionsSupported = 0;
   5.261 +      nttic->V6Transmit.TcpOptionsSupported = 0;
   5.262 +      nttic->V6Transmit.TcpChecksum = 0;
   5.263 +      nttic->V6Transmit.UdpChecksum = 0;
   5.264 +      nttic->V6Receive.IpOptionsSupported = 0;
   5.265 +      nttic->V6Receive.TcpOptionsSupported = 0;
   5.266 +      nttic->V6Receive.TcpChecksum = 0;
   5.267 +      nttic->V6Receive.UdpChecksum = 0;
   5.268 +
   5.269 +#ifdef OFFLOAD_LARGE_SEND
   5.270 +      /* offset from start of current NTO to start of next NTO */
   5.271 +      nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   5.272 +        + nto->TaskBufferLength;
   5.273 +
   5.274 +      /* fill in second nto */
   5.275 +      nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + nto->OffsetNextTask);
   5.276 +      nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   5.277 +      nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   5.278 +      nto->Task = TcpLargeSendNdisTask;
   5.279 +      nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
   5.280 +
   5.281 +      /* fill in large send struct */
   5.282 +      nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
   5.283 +      nttls->Version = 0;
   5.284 +      nttls->MaxOffLoadSize = 1024*64; /* made up, fixme */
   5.285 +      nttls->MinSegmentCount = 4; /* also made up */
   5.286 +      nttls->TcpOptions = FALSE;
   5.287 +      nttls->IpOptions = FALSE;
   5.288 +#endif
   5.289 +      nto->OffsetNextTask = 0; /* last one */
   5.290 +
   5.291 +      used_temp_buffer = FALSE;
   5.292 +      break;
   5.293 +    default:
   5.294 +      KdPrint(("Get Unknown OID 0x%x\n", Oid));
   5.295 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.296 +  }
   5.297 +
   5.298 +  if (!NT_SUCCESS(status))
   5.299 +  {
   5.300 +  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returned error)\n"));
   5.301 +    return status;
   5.302 +  }
   5.303 +
   5.304 +  if (len > InformationBufferLength)
   5.305 +  {
   5.306 +    *BytesNeeded = len;
   5.307 +    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (BUFFER_TOO_SHORT)\n"));
   5.308 +    return NDIS_STATUS_BUFFER_TOO_SHORT;
   5.309 +  }
   5.310 +
   5.311 +  *BytesWritten = len;
   5.312 +  if (len && used_temp_buffer)
   5.313 +  {
   5.314 +    NdisMoveMemory((PUCHAR)InformationBuffer, data, len);
   5.315 +  }
   5.316 +
   5.317 +  //KdPrint(("Got OID 0x%x\n", Oid));
   5.318 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.319 +
   5.320 +  return status;
   5.321 +}
   5.322 +
   5.323 +NDIS_STATUS 
   5.324 +XenNet_SetInformation(
   5.325 +  IN NDIS_HANDLE MiniportAdapterContext,
   5.326 +  IN NDIS_OID Oid,
   5.327 +  IN PVOID InformationBuffer,
   5.328 +  IN ULONG InformationBufferLength,
   5.329 +  OUT PULONG BytesRead,
   5.330 +  OUT PULONG BytesNeeded
   5.331 +  )
   5.332 +{
   5.333 +  NTSTATUS status;
   5.334 +  struct xennet_info *xi = MiniportAdapterContext;
   5.335 +  PULONG64 data = InformationBuffer;
   5.336 +  PNDIS_TASK_OFFLOAD_HEADER ntoh;
   5.337 +  PNDIS_TASK_OFFLOAD nto;
   5.338 +  PNDIS_TASK_TCP_IP_CHECKSUM nttic;
   5.339 +  int offset;
   5.340 +
   5.341 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.342 +
   5.343 +  UNREFERENCED_PARAMETER(MiniportAdapterContext);
   5.344 +  UNREFERENCED_PARAMETER(InformationBufferLength);
   5.345 +  UNREFERENCED_PARAMETER(BytesRead);
   5.346 +  UNREFERENCED_PARAMETER(BytesNeeded);
   5.347 +
   5.348 +  switch(Oid)
   5.349 +  {
   5.350 +    case OID_GEN_SUPPORTED_LIST:
   5.351 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.352 +      KdPrint(("Unsupported set OID_GEN_SUPPORTED_LIST\n"));
   5.353 +      break;
   5.354 +    case OID_GEN_HARDWARE_STATUS:
   5.355 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.356 +      KdPrint(("Unsupported set OID_GEN_HARDWARE_STATUS\n"));
   5.357 +      break;
   5.358 +    case OID_GEN_MEDIA_SUPPORTED:
   5.359 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.360 +      KdPrint(("Unsupported set OID_GEN_MEDIA_SUPPORTED\n"));
   5.361 +      break;
   5.362 +    case OID_GEN_MEDIA_IN_USE:
   5.363 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.364 +      KdPrint(("Unsupported set OID_GEN_MEDIA_IN_USE\n"));
   5.365 +      break;
   5.366 +    case OID_GEN_MAXIMUM_LOOKAHEAD:
   5.367 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.368 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_LOOKAHEAD\n"));
   5.369 +      break;
   5.370 +    case OID_GEN_MAXIMUM_FRAME_SIZE:
   5.371 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.372 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_FRAME_SIZE\n"));
   5.373 +      break;
   5.374 +    case OID_GEN_LINK_SPEED:
   5.375 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.376 +      KdPrint(("Unsupported set OID_GEN_LINK_SPEED\n"));
   5.377 +      break;
   5.378 +    case OID_GEN_TRANSMIT_BUFFER_SPACE:
   5.379 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.380 +      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
   5.381 +      break;
   5.382 +    case OID_GEN_RECEIVE_BUFFER_SPACE:
   5.383 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.384 +      KdPrint(("Unsupported set OID_GEN_RECEIVE_BUFFER_SPACE\n"));
   5.385 +      break;
   5.386 +    case OID_GEN_TRANSMIT_BLOCK_SIZE:
   5.387 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.388 +      KdPrint(("Unsupported set OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
   5.389 +      break;
   5.390 +    case OID_GEN_RECEIVE_BLOCK_SIZE:
   5.391 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.392 +      KdPrint(("Unsupported set OID_GEN_RECEIVE_BLOCK_SIZE\n"));
   5.393 +      break;
   5.394 +    case OID_GEN_VENDOR_ID:
   5.395 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.396 +      KdPrint(("Unsupported set OID_GEN_VENDOR_ID\n"));
   5.397 +      break;
   5.398 +    case OID_GEN_VENDOR_DESCRIPTION:
   5.399 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.400 +      KdPrint(("Unsupported set OID_GEN_VENDOR_DESCRIPTION\n"));
   5.401 +      break;
   5.402 +    case OID_GEN_CURRENT_PACKET_FILTER:
   5.403 +      KdPrint(("Set OID_GEN_CURRENT_PACKET_FILTER\n"));
   5.404 +      xi->packet_filter = *(ULONG *)data;
   5.405 +      status = NDIS_STATUS_SUCCESS;
   5.406 +      break;
   5.407 +    case OID_GEN_CURRENT_LOOKAHEAD:
   5.408 +      KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d\n", *(int *)data));
   5.409 +      // TODO: We should do this...
   5.410 +      status = NDIS_STATUS_SUCCESS;
   5.411 +      break;
   5.412 +    case OID_GEN_DRIVER_VERSION:
   5.413 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.414 +      KdPrint(("Unsupported set OID_GEN_DRIVER_VERSION\n"));
   5.415 +      break;
   5.416 +    case OID_GEN_MAXIMUM_TOTAL_SIZE:
   5.417 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.418 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
   5.419 +      break;
   5.420 +    case OID_GEN_PROTOCOL_OPTIONS:
   5.421 +      KdPrint(("Unsupported set OID_GEN_PROTOCOL_OPTIONS\n"));
   5.422 +      // TODO - actually do this...
   5.423 +      status = NDIS_STATUS_SUCCESS;
   5.424 +      break;
   5.425 +    case OID_GEN_MAC_OPTIONS:
   5.426 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.427 +      KdPrint(("Unsupported set OID_GEN_MAC_OPTIONS\n"));
   5.428 +      break;
   5.429 +    case OID_GEN_MEDIA_CONNECT_STATUS:
   5.430 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.431 +      KdPrint(("Unsupported set OID_GEN_MEDIA_CONNECT_STATUS\n"));
   5.432 +      break;
   5.433 +    case OID_GEN_MAXIMUM_SEND_PACKETS:
   5.434 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.435 +      KdPrint(("Unsupported set OID_GEN_MAXIMUM_SEND_PACKETS\n"));
   5.436 +      break;
   5.437 +    case OID_GEN_XMIT_OK:
   5.438 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.439 +      KdPrint(("Unsupported set OID_GEN_XMIT_OK\n"));
   5.440 +      break;
   5.441 +    case OID_GEN_RCV_OK:
   5.442 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.443 +      KdPrint(("Unsupported set OID_GEN_RCV_OK\n"));
   5.444 +      break;
   5.445 +    case OID_GEN_XMIT_ERROR:
   5.446 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.447 +      KdPrint(("Unsupported set OID_GEN_XMIT_ERROR\n"));
   5.448 +      break;
   5.449 +    case OID_GEN_RCV_ERROR:
   5.450 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.451 +      KdPrint(("Unsupported set OID_GEN_RCV_ERROR\n"));
   5.452 +      break;
   5.453 +    case OID_GEN_RCV_NO_BUFFER:
   5.454 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.455 +      KdPrint(("Unsupported set OID_GEN_RCV_NO_BUFFER\n"));
   5.456 +      break;
   5.457 +    case OID_802_3_PERMANENT_ADDRESS:
   5.458 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.459 +      KdPrint(("Unsupported set OID_802_3_PERMANENT_ADDRESS\n"));
   5.460 +      break;
   5.461 +    case OID_802_3_CURRENT_ADDRESS:
   5.462 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.463 +      KdPrint(("Unsupported set OID_802_3_CURRENT_ADDRESS\n"));
   5.464 +      break;
   5.465 +    case OID_802_3_MULTICAST_LIST:
   5.466 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.467 +      KdPrint(("Unsupported set OID_802_3_MULTICAST_LIST\n"));
   5.468 +      break;
   5.469 +    case OID_802_3_MAXIMUM_LIST_SIZE:
   5.470 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.471 +      KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
   5.472 +      break;
   5.473 +    case OID_TCP_TASK_OFFLOAD:
   5.474 +      // Just fake this for now... ultimately we need to manually calc rx checksum if offload is disabled by windows
   5.475 +      status = NDIS_STATUS_SUCCESS;
   5.476 +      KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
   5.477 +      // we should disable everything here, then enable what has been set
   5.478 +      ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
   5.479 +      *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
   5.480 +      offset = ntoh->OffsetFirstTask;
   5.481 +      nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
   5.482 +      while (offset != 0)
   5.483 +      {
   5.484 +        *BytesRead += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer);
   5.485 +        nto = (PNDIS_TASK_OFFLOAD)(((PUCHAR)nto) + offset);
   5.486 +        switch (nto->Task)
   5.487 +        {
   5.488 +        case TcpIpChecksumNdisTask:
   5.489 +          *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   5.490 +          KdPrint(("TcpIpChecksumNdisTask\n"));
   5.491 +          nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   5.492 +          KdPrint(("  V4Transmit.IpOptionsSupported  = %d\n", nttic->V4Transmit.IpOptionsSupported));
   5.493 +          KdPrint(("  V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported));
   5.494 +          KdPrint(("  V4Transmit.TcpChecksum         = %d\n", nttic->V4Transmit.TcpChecksum));
   5.495 +          KdPrint(("  V4Transmit.UdpChecksum         = %d\n", nttic->V4Transmit.UdpChecksum));
   5.496 +          KdPrint(("  V4Transmit.IpChecksum          = %d\n", nttic->V4Transmit.IpChecksum));
   5.497 +          KdPrint(("  V4Receive.IpOptionsSupported   = %d\n", nttic->V4Receive.IpOptionsSupported));
   5.498 +          KdPrint(("  V4Receive.TcpOptionsSupported  = %d\n", nttic->V4Receive.TcpOptionsSupported));
   5.499 +          KdPrint(("  V4Receive.TcpChecksum          = %d\n", nttic->V4Receive.TcpChecksum));
   5.500 +          KdPrint(("  V4Receive.UdpChecksum          = %d\n", nttic->V4Receive.UdpChecksum));
   5.501 +          KdPrint(("  V4Receive.IpChecksum           = %d\n", nttic->V4Receive.IpChecksum));
   5.502 +          KdPrint(("  V6Transmit.IpOptionsSupported  = %d\n", nttic->V6Transmit.IpOptionsSupported));
   5.503 +          KdPrint(("  V6Transmit.TcpOptionsSupported = %d\n", nttic->V6Transmit.TcpOptionsSupported));
   5.504 +          KdPrint(("  V6Transmit.TcpChecksum         = %d\n", nttic->V6Transmit.TcpChecksum));
   5.505 +          KdPrint(("  V6Transmit.UdpChecksum         = %d\n", nttic->V6Transmit.UdpChecksum));
   5.506 +          KdPrint(("  V6Receive.IpOptionsSupported   = %d\n", nttic->V6Receive.IpOptionsSupported));
   5.507 +          KdPrint(("  V6Receive.TcpOptionsSupported  = %d\n", nttic->V6Receive.TcpOptionsSupported));
   5.508 +          KdPrint(("  V6Receive.TcpChecksum          = %d\n", nttic->V6Receive.TcpChecksum));
   5.509 +          KdPrint(("  V6Receive.UdpChecksum          = %d\n", nttic->V6Receive.UdpChecksum));
   5.510 +          break;
   5.511 +        default:
   5.512 +          KdPrint(("  Unknown Task %d\n", nto->Task));
   5.513 +        }
   5.514 +        offset = nto->OffsetNextTask;
   5.515 +      }
   5.516 +      break;
   5.517 +    default:
   5.518 +      KdPrint(("Set Unknown OID 0x%x\n", Oid));
   5.519 +      status = NDIS_STATUS_NOT_SUPPORTED;
   5.520 +      break;
   5.521 +  }
   5.522 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.523 +  return status;
   5.524 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xennet/xennet_rx.c	Sun Mar 02 16:54:23 2008 +1100
     6.3 @@ -0,0 +1,309 @@
     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 "xennet.h"
    6.25 +
    6.26 +static USHORT
    6.27 +get_rx_id_from_freelist(struct xennet_info *xi)
    6.28 +{
    6.29 +  if (xi->rx_id_free == 0)
    6.30 +    return 0xFFFF;
    6.31 +  xi->rx_id_free--;
    6.32 +  return xi->rx_id_list[xi->rx_id_free];
    6.33 +}
    6.34 +
    6.35 +static VOID
    6.36 +put_rx_id_on_freelist(struct xennet_info *xi, USHORT id)
    6.37 +{
    6.38 +  xi->rx_id_list[xi->rx_id_free] = id;
    6.39 +  xi->rx_id_free++;
    6.40 +}
    6.41 +
    6.42 +// Called at DISPATCH_LEVEL with rx lock held
    6.43 +static NDIS_STATUS
    6.44 +XenNet_RxBufferAlloc(struct xennet_info *xi)
    6.45 +{
    6.46 +  unsigned short id;
    6.47 +  PMDL mdl;
    6.48 +  int i, batch_target, notify;
    6.49 +  RING_IDX req_prod = xi->rx.req_prod_pvt;
    6.50 +  netif_rx_request_t *req;
    6.51 +#if defined(XEN_PROFILE)
    6.52 +  LARGE_INTEGER tsc, dummy;
    6.53 +#endif
    6.54 +
    6.55 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    6.56 +#if defined(XEN_PROFILE)
    6.57 +  tsc = KeQueryPerformanceCounter(&dummy);
    6.58 +#endif
    6.59 +
    6.60 +  batch_target = xi->rx_target - (req_prod - xi->rx.rsp_cons);
    6.61 +
    6.62 +  for (i = 0; i < batch_target; i++)
    6.63 +  {
    6.64 +    mdl = get_page_from_freelist(xi);
    6.65 +    if (mdl == NULL)
    6.66 +      break;
    6.67 +
    6.68 +    /* Give to netback */
    6.69 +    id = get_rx_id_from_freelist(xi);
    6.70 +    if (id == 0xFFFF)
    6.71 +    {
    6.72 +      put_page_on_freelist(xi, mdl);
    6.73 +      break;
    6.74 +    }
    6.75 +//    KdPrint((__DRIVER_NAME "     id = %d\n", id));
    6.76 +    ASSERT(xi->rx_buffers[id] == NULL);
    6.77 +    xi->rx_buffers[id] = mdl;
    6.78 +    req = RING_GET_REQUEST(&xi->rx, req_prod + i);
    6.79 +    req->gref = get_grant_ref(mdl);
    6.80 +    req->id = id;
    6.81 +  }
    6.82 +
    6.83 +  xi->rx.req_prod_pvt = req_prod + i;
    6.84 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->rx, notify);
    6.85 +  if (notify)
    6.86 +  {
    6.87 +    xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
    6.88 +      xi->event_channel);
    6.89 +  }
    6.90 +
    6.91 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    6.92 +
    6.93 +#if defined(XEN_PROFILE)
    6.94 +  ProfTime_RxBufferAlloc.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
    6.95 +  ProfCount_RxBufferAlloc++;
    6.96 +#endif
    6.97 +
    6.98 +  return NDIS_STATUS_SUCCESS;
    6.99 +}
   6.100 +
   6.101 +// Called at DISPATCH_LEVEL
   6.102 +NDIS_STATUS
   6.103 +XenNet_RxBufferCheck(struct xennet_info *xi)
   6.104 +{
   6.105 +  RING_IDX cons, prod;
   6.106 +  PNDIS_PACKET packets[NET_RX_RING_SIZE];
   6.107 +  ULONG packet_count;
   6.108 +  PMDL mdl;
   6.109 +  int moretodo;
   6.110 +  KIRQL OldIrql;
   6.111 +  struct netif_rx_response *rxrsp = NULL;
   6.112 +  int more_frags = 0;
   6.113 +  NDIS_STATUS status;
   6.114 +  LARGE_INTEGER time_received;
   6.115 +  USHORT id;
   6.116 +#if defined(XEN_PROFILE)
   6.117 +  LARGE_INTEGER tsc, dummy;
   6.118 +#endif
   6.119 +  
   6.120 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   6.121 +
   6.122 +#if defined(XEN_PROFILE)
   6.123 +  tsc = KeQueryPerformanceCounter(&dummy);
   6.124 +#endif
   6.125 +
   6.126 +  ASSERT(xi->connected);
   6.127 +
   6.128 +  NdisGetCurrentSystemTime(&time_received);
   6.129 +  KeAcquireSpinLock(&xi->rx_lock, &OldIrql);
   6.130 +
   6.131 +  packet_count = 0;
   6.132 +  do {
   6.133 +    prod = xi->rx.sring->rsp_prod;
   6.134 +    KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
   6.135 +
   6.136 +    for (cons = xi->rx.rsp_cons; cons != prod; cons++) {
   6.137 +
   6.138 +      rxrsp = RING_GET_RESPONSE(&xi->rx, cons);
   6.139 +      id = rxrsp->id;
   6.140 +      mdl = xi->rx_buffers[id];
   6.141 +      xi->rx_buffers[id] = NULL;
   6.142 +      put_rx_id_on_freelist(xi, id);
   6.143 +      if (rxrsp->status <= 0
   6.144 +        || rxrsp->offset + rxrsp->status > PAGE_SIZE)
   6.145 +      {
   6.146 +        KdPrint((__DRIVER_NAME ": Error: rxrsp offset %d, size %d\n",
   6.147 +          rxrsp->offset, rxrsp->status));
   6.148 +        continue;
   6.149 +      }
   6.150 +      if (!more_frags) // handling the packet's 1st buffer
   6.151 +      {
   6.152 +        NdisAllocatePacket(&status, &packets[packet_count], xi->packet_pool);
   6.153 +        ASSERT(status == NDIS_STATUS_SUCCESS);
   6.154 +        NDIS_SET_PACKET_HEADER_SIZE(packets[packet_count], XN_HDR_SIZE);
   6.155 +      }
   6.156 +
   6.157 +      NdisAdjustBufferLength(mdl, rxrsp->status);
   6.158 +      NdisChainBufferAtBack(packets[packet_count], mdl);
   6.159 +
   6.160 +      ASSERT(!(rxrsp->flags & NETRXF_extra_info)); // not used on RX
   6.161 +
   6.162 +      more_frags = rxrsp->flags & NETRXF_more_data;
   6.163 +
   6.164 +      /* Packet done, pass it up */
   6.165 +      if (!more_frags)
   6.166 +      {
   6.167 +        xi->stat_rx_ok++;
   6.168 +        InterlockedIncrement(&xi->rx_outstanding);
   6.169 +        NDIS_SET_PACKET_STATUS(packets[packet_count], NDIS_STATUS_SUCCESS);
   6.170 +        NDIS_SET_PACKET_TIME_RECEIVED(packets[packet_count], time_received.QuadPart);
   6.171 +        packet_count++;
   6.172 +        if (packet_count == NET_RX_RING_SIZE)
   6.173 +        {
   6.174 +          NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
   6.175 +          packet_count = 0;
   6.176 +        }
   6.177 +      }
   6.178 +    }
   6.179 +    xi->rx.rsp_cons = prod;
   6.180 +
   6.181 +    RING_FINAL_CHECK_FOR_RESPONSES(&xi->rx, moretodo);
   6.182 +  } while (moretodo);
   6.183 +
   6.184 +  if (more_frags)
   6.185 +  {
   6.186 +    KdPrint((__DRIVER_NAME "     Missing fragments\n"));
   6.187 +    XenNet_ReturnPacket(xi, packets[packet_count]);
   6.188 +  }
   6.189 +
   6.190 +  if (packet_count != 0)
   6.191 +  {
   6.192 +    NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
   6.193 +  }
   6.194 +
   6.195 +  /* Give netback more buffers */
   6.196 +  XenNet_RxBufferAlloc(xi);
   6.197 +
   6.198 +  KeReleaseSpinLock(&xi->rx_lock, OldIrql);
   6.199 +
   6.200 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.201 +
   6.202 +#if defined(XEN_PROFILE)
   6.203 +  ProfTime_RxBufferCheck.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   6.204 +  ProfCount_RxBufferCheck++;
   6.205 +#endif
   6.206 +
   6.207 +  return NDIS_STATUS_SUCCESS;
   6.208 +}
   6.209 +
   6.210 +VOID
   6.211 +XenNet_ReturnPacket(
   6.212 +  IN NDIS_HANDLE MiniportAdapterContext,
   6.213 +  IN PNDIS_PACKET Packet
   6.214 +  )
   6.215 +{
   6.216 +  struct xennet_info *xi = MiniportAdapterContext;
   6.217 +  PMDL mdl;
   6.218 +#if defined(XEN_PROFILE)
   6.219 +  LARGE_INTEGER tsc, dummy;
   6.220 +#endif
   6.221 +
   6.222 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   6.223 +
   6.224 +#if defined(XEN_PROFILE)
   6.225 +  tsc = KeQueryPerformanceCounter(&dummy);
   6.226 +#endif
   6.227 +
   6.228 +  NdisUnchainBufferAtBack(Packet, &mdl);
   6.229 +  while (mdl)
   6.230 +  {
   6.231 +    NdisAdjustBufferLength(mdl, PAGE_SIZE);
   6.232 +    put_page_on_freelist(xi, mdl);
   6.233 +    NdisUnchainBufferAtBack(Packet, &mdl);
   6.234 +  }
   6.235 +
   6.236 +  NdisFreePacket(Packet);
   6.237 +  
   6.238 +  InterlockedDecrement(&xi->rx_outstanding);
   6.239 +
   6.240 +  // if we are no longer connected then _halt needs to know when rx_outstanding reaches zero
   6.241 +  if (!xi->connected && !xi->rx_outstanding)
   6.242 +    KeSetEvent(&xi->shutdown_event, 1, FALSE);  
   6.243 +
   6.244 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.245 +
   6.246 +#if defined(XEN_PROFILE)
   6.247 +  ProfTime_ReturnPacket.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   6.248 +  ProfCount_ReturnPacket++;
   6.249 +#endif
   6.250 +}
   6.251 +
   6.252 +/*
   6.253 +   Free all Rx buffers (on halt, for example) 
   6.254 +   The ring must be stopped at this point.
   6.255 +*/
   6.256 +static void
   6.257 +XenNet_RxBufferFree(struct xennet_info *xi)
   6.258 +{
   6.259 +  int i;
   6.260 +  PMDL mdl;
   6.261 +
   6.262 +  ASSERT(!xi->connected);
   6.263 +
   6.264 +  for (i = 0; i < NET_RX_RING_SIZE; i++)
   6.265 +  {
   6.266 +    if (!xi->rx_buffers[i])
   6.267 +      continue;
   6.268 +
   6.269 +    mdl = xi->rx_buffers[i];
   6.270 +    NdisAdjustBufferLength(mdl, PAGE_SIZE);
   6.271 +    put_page_on_freelist(xi, mdl);
   6.272 +  }
   6.273 +}
   6.274 +
   6.275 +BOOLEAN
   6.276 +XenNet_RxInit(xennet_info_t *xi)
   6.277 +{
   6.278 +  USHORT i;
   6.279 +
   6.280 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   6.281 +
   6.282 +  xi->rx_mdl = AllocatePage();
   6.283 +  xi->rx_pgs = MmGetMdlVirtualAddress(xi->rx_mdl);
   6.284 +  SHARED_RING_INIT(xi->rx_pgs);
   6.285 +  FRONT_RING_INIT(&xi->rx, xi->rx_pgs, PAGE_SIZE);
   6.286 +  xi->rx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
   6.287 +    xi->XenInterface.InterfaceHeader.Context, 0,
   6.288 +    *MmGetMdlPfnArray(xi->rx_mdl), FALSE);
   6.289 +  xi->rx_id_free = 0;
   6.290 +  for (i = 0; i < NET_RX_RING_SIZE; i++)
   6.291 +  {
   6.292 +    xi->rx_buffers[i] = NULL;
   6.293 +    put_rx_id_on_freelist(xi, i);
   6.294 +  }
   6.295 +  XenNet_RxBufferAlloc(xi);
   6.296 +
   6.297 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.298 +
   6.299 +  return TRUE;
   6.300 +}
   6.301 +
   6.302 +BOOLEAN
   6.303 +XenNet_RxShutdown(xennet_info_t *xi)
   6.304 +{
   6.305 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   6.306 +
   6.307 +  XenNet_RxBufferFree(xi);
   6.308 +
   6.309 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.310 +
   6.311 +  return TRUE;
   6.312 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xennet/xennet_tx.c	Sun Mar 02 16:54:23 2008 +1100
     7.3 @@ -0,0 +1,359 @@
     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 "xennet.h"
    7.25 +
    7.26 +static USHORT
    7.27 +get_tx_id_from_freelist(struct xennet_info *xi)
    7.28 +{
    7.29 +  if (xi->tx_id_free == 0)
    7.30 +    return 0xFFFF;
    7.31 +  xi->tx_id_free--;
    7.32 +  return xi->tx_id_list[xi->tx_id_free];
    7.33 +}
    7.34 +
    7.35 +static VOID
    7.36 +put_tx_id_on_freelist(struct xennet_info *xi, USHORT id)
    7.37 +{
    7.38 +  xi->tx_id_list[xi->tx_id_free] = id;
    7.39 +  xi->tx_id_free++;
    7.40 +}
    7.41 +
    7.42 +/* Called at DISPATCH_LEVEL with tx_lock held */
    7.43 +static PMDL
    7.44 +XenNet_Linearize(struct xennet_info *xi, PNDIS_PACKET Packet)
    7.45 +{
    7.46 +  PMDL pmdl;
    7.47 +  char *start;
    7.48 +  PNDIS_BUFFER buffer;
    7.49 +  PVOID buff_va;
    7.50 +  UINT buff_len;
    7.51 +  UINT tot_buff_len;
    7.52 +#if defined(XEN_PROFILE)
    7.53 +  LARGE_INTEGER tsc, dummy;
    7.54 +#endif
    7.55 +
    7.56 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    7.57 +
    7.58 +#if defined(XEN_PROFILE)
    7.59 +  tsc = KeQueryPerformanceCounter(&dummy);
    7.60 +#endif
    7.61 +
    7.62 +  NdisGetFirstBufferFromPacketSafe(Packet, &buffer, &buff_va, &buff_len,
    7.63 +    &tot_buff_len, NormalPagePriority);
    7.64 +  ASSERT(tot_buff_len <= XN_MAX_PKT_SIZE);
    7.65 +
    7.66 +  pmdl = get_page_from_freelist(xi);
    7.67 +  if (!pmdl)
    7.68 +  {
    7.69 +    KdPrint(("Could not allocate MDL for linearization\n"));
    7.70 +    return NULL;
    7.71 +  }
    7.72 +
    7.73 +  start = MmGetMdlVirtualAddress(pmdl);
    7.74 +
    7.75 +  while (buffer)
    7.76 +  {
    7.77 +    NdisQueryBufferSafe(buffer, &buff_va, &buff_len, NormalPagePriority);
    7.78 +    RtlCopyMemory(start, buff_va, buff_len);
    7.79 +    start += buff_len;
    7.80 +    NdisGetNextBuffer(buffer, &buffer);
    7.81 +  }
    7.82 +
    7.83 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    7.84 +#if defined(XEN_PROFILE)
    7.85 +  ProfTime_Linearize.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
    7.86 +  ProfCount_Linearize++;
    7.87 +#endif
    7.88 +
    7.89 +  return pmdl;
    7.90 +}
    7.91 +
    7.92 +static VOID
    7.93 +XenNet_SendQueuedPackets(struct xennet_info *xi)
    7.94 +{
    7.95 +  PLIST_ENTRY entry;
    7.96 +  PNDIS_PACKET packet;
    7.97 +  KIRQL OldIrql;
    7.98 +  struct netif_tx_request *tx;
    7.99 +  unsigned short id;
   7.100 +  int notify;
   7.101 +  PMDL pmdl;
   7.102 +  UINT pkt_size;
   7.103 +#if defined(XEN_PROFILE)
   7.104 +  LARGE_INTEGER tsc, dummy;
   7.105 +  KIRQL OldIrql2;
   7.106 +#endif
   7.107 +
   7.108 +#if defined(XEN_PROFILE)
   7.109 +  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql2);
   7.110 +  tsc = KeQueryPerformanceCounter(&dummy);
   7.111 +#endif
   7.112 +
   7.113 +  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
   7.114 +
   7.115 +  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   7.116 +  /* if empty, the above returns head*, not NULL */
   7.117 +  while (entry != &xi->tx_waiting_pkt_list)
   7.118 +  {
   7.119 +    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   7.120 +
   7.121 +    NdisQueryPacket(packet, NULL, NULL, NULL, &pkt_size);
   7.122 +
   7.123 +    id = get_tx_id_from_freelist(xi);
   7.124 +    if (id == 0xFFFF)
   7.125 +    {
   7.126 +      /* whups, out of space on the ring. requeue and get out */
   7.127 +      InsertHeadList(&xi->tx_waiting_pkt_list, entry);
   7.128 +      break;
   7.129 +    }
   7.130 +    //KdPrint(("sending pkt, len %d\n", pkt_size));
   7.131 +    ASSERT(xi->tx_pkts[id] == NULL);
   7.132 +    xi->tx_pkts[id] = packet;
   7.133 +
   7.134 +    pmdl = XenNet_Linearize(xi, packet);
   7.135 +    if (!pmdl)
   7.136 +    {
   7.137 +      KdPrint((__DRIVER_NAME "Couldn't linearize packet!\n"));
   7.138 +      NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   7.139 +      break;
   7.140 +    }
   7.141 +
   7.142 +    /* NOTE: 
   7.143 +     * We use the UCHAR[3*sizeof(PVOID)] array in each packet's MiniportReservedEx thusly:
   7.144 +     * 0: PMDL to linearized data
   7.145 +     * sizeof(PVOID)+: LIST_ENTRY for placing packet on the waiting pkt list
   7.146 +     */
   7.147 +    *(PMDL *)&packet->MiniportReservedEx = pmdl;
   7.148 +
   7.149 +    tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   7.150 +    tx->id = id;
   7.151 +    tx->gref = get_grant_ref(pmdl);
   7.152 +    tx->offset = (uint16_t)MmGetMdlByteOffset(pmdl);
   7.153 +    tx->size = (UINT16)pkt_size;
   7.154 +    // NETTXF_csum_blank should only be used for tcp and udp packets...    
   7.155 +    tx->flags = 0; //NETTXF_csum_blank;
   7.156 +
   7.157 +    xi->tx.req_prod_pvt++;
   7.158 +
   7.159 +    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   7.160 +  }
   7.161 +
   7.162 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->tx, notify);
   7.163 +  if (notify)
   7.164 +  {
   7.165 +    xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
   7.166 +      xi->event_channel);
   7.167 +  }
   7.168 +
   7.169 +  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
   7.170 +#if defined(XEN_PROFILE)
   7.171 +  ProfTime_SendQueuedPackets.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   7.172 +  ProfCount_SendQueuedPackets++;
   7.173 +  KeLowerIrql(OldIrql2);
   7.174 +#endif
   7.175 +}
   7.176 +
   7.177 +// Called at DISPATCH_LEVEL
   7.178 +NDIS_STATUS
   7.179 +XenNet_TxBufferGC(struct xennet_info *xi)
   7.180 +{
   7.181 +  RING_IDX cons, prod;
   7.182 +  unsigned short id;
   7.183 +  PNDIS_PACKET packet;
   7.184 +  int moretodo;
   7.185 +#if defined(XEN_PROFILE)
   7.186 +  LARGE_INTEGER tsc, dummy;
   7.187 +#endif
   7.188 +
   7.189 +  ASSERT(xi->connected);
   7.190 +  ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
   7.191 +
   7.192 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   7.193 +
   7.194 +#if defined(XEN_PROFILE)
   7.195 +  tsc = KeQueryPerformanceCounter(&dummy);
   7.196 +#endif
   7.197 +
   7.198 +  KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
   7.199 +
   7.200 +  do {
   7.201 +    prod = xi->tx.sring->rsp_prod;
   7.202 +    KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
   7.203 +
   7.204 +    for (cons = xi->tx.rsp_cons; cons != prod; cons++) {
   7.205 +      struct netif_tx_response *txrsp;
   7.206 +
   7.207 +      txrsp = RING_GET_RESPONSE(&xi->tx, cons);
   7.208 +      if (txrsp->status == NETIF_RSP_NULL)
   7.209 +        continue; // should this happen? what about the page?
   7.210 +      id  = txrsp->id;
   7.211 +      packet = xi->tx_pkts[id];
   7.212 +      xi->tx_pkts[id] = NULL;
   7.213 +      put_tx_id_on_freelist(xi, id);
   7.214 +      put_page_on_freelist(xi, *(PMDL *)packet->MiniportReservedEx);
   7.215 +      NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_SUCCESS);
   7.216 +
   7.217 +      InterlockedDecrement(&xi->tx_outstanding);
   7.218 +      xi->stat_tx_ok++;
   7.219 +    }
   7.220 +
   7.221 +    xi->tx.rsp_cons = prod;
   7.222 +
   7.223 +    RING_FINAL_CHECK_FOR_RESPONSES(&xi->tx, moretodo);
   7.224 +  } while (moretodo);
   7.225 +
   7.226 +  KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   7.227 +
   7.228 +  /* if queued packets, send them now */
   7.229 +  XenNet_SendQueuedPackets(xi);
   7.230 +
   7.231 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   7.232 +
   7.233 +#if defined(XEN_PROFILE)
   7.234 +  ProfTime_TxBufferGC.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   7.235 +  ProfCount_TxBufferGC++;
   7.236 +#endif
   7.237 +
   7.238 +  return NDIS_STATUS_SUCCESS;
   7.239 +}
   7.240 +
   7.241 +VOID
   7.242 +XenNet_SendPackets(
   7.243 +  IN NDIS_HANDLE MiniportAdapterContext,
   7.244 +  IN PPNDIS_PACKET PacketArray,
   7.245 +  IN UINT NumberOfPackets
   7.246 +  )
   7.247 +{
   7.248 +  struct xennet_info *xi = MiniportAdapterContext;
   7.249 +  PNDIS_PACKET curr_packet;
   7.250 +  UINT i;
   7.251 +  PLIST_ENTRY entry;
   7.252 +  KIRQL OldIrql;
   7.253 +#if defined(XEN_PROFILE)
   7.254 +  LARGE_INTEGER tsc, dummy;
   7.255 +  KIRQL OldIrql2;
   7.256 +#endif
   7.257 +
   7.258 +#if defined(XEN_PROFILE)
   7.259 +  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql2);
   7.260 +  tsc = KeQueryPerformanceCounter(&dummy);
   7.261 +#endif
   7.262 +
   7.263 +  KeAcquireSpinLock(&xi->tx_lock, &OldIrql);
   7.264 +
   7.265 +  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   7.266 +  for (i = 0; i < NumberOfPackets; i++)
   7.267 +  {
   7.268 +    curr_packet = PacketArray[i];
   7.269 +    ASSERT(curr_packet);
   7.270 +    entry = (PLIST_ENTRY)&curr_packet->MiniportReservedEx[sizeof(PVOID)];
   7.271 +    InsertTailList(&xi->tx_waiting_pkt_list, entry);
   7.272 +    InterlockedIncrement(&xi->tx_outstanding);
   7.273 +  }
   7.274 +  KeReleaseSpinLock(&xi->tx_lock, OldIrql);
   7.275 +
   7.276 +#if defined(XEN_PROFILE)
   7.277 +  ProfTime_SendPackets.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   7.278 +  ProfCount_SendPackets++;
   7.279 +  KeLowerIrql(OldIrql2);
   7.280 +#endif
   7.281 +
   7.282 +  XenNet_SendQueuedPackets(xi);
   7.283 +
   7.284 +#if defined(XEN_PROFILE)
   7.285 +  if ((ProfCount_SendPackets & 1023) == 0)
   7.286 +  {
   7.287 +    KdPrint((__DRIVER_NAME "     TxBufferGC        Count = %10d, Avg Time = %10ld\n", ProfCount_TxBufferGC, (ProfCount_TxBufferGC == 0)?0:(ProfTime_TxBufferGC.QuadPart / ProfCount_TxBufferGC)));
   7.288 +    KdPrint((__DRIVER_NAME "     TxBufferFree      Count = %10d, Avg Time = %10ld\n", ProfCount_TxBufferFree, (ProfCount_TxBufferFree == 0)?0:(ProfTime_TxBufferFree.QuadPart / ProfCount_TxBufferFree)));
   7.289 +    KdPrint((__DRIVER_NAME "     RxBufferAlloc     Count = %10d, Avg Time = %10ld\n", ProfCount_RxBufferAlloc, (ProfCount_RxBufferAlloc == 0)?0:(ProfTime_RxBufferAlloc.QuadPart / ProfCount_RxBufferAlloc)));
   7.290 +    KdPrint((__DRIVER_NAME "     RxBufferFree      Count = %10d, Avg Time = %10ld\n", ProfCount_RxBufferFree, (ProfCount_RxBufferFree == 0)?0:(ProfTime_RxBufferFree.QuadPart / ProfCount_RxBufferFree)));
   7.291 +    KdPrint((__DRIVER_NAME "     ReturnPacket      Count = %10d, Avg Time = %10ld\n", ProfCount_ReturnPacket, (ProfCount_ReturnPacket == 0)?0:(ProfTime_ReturnPacket.QuadPart / ProfCount_ReturnPacket)));
   7.292 +    KdPrint((__DRIVER_NAME "     RxBufferCheck     Count = %10d, Avg Time = %10ld\n", ProfCount_RxBufferCheck, (ProfCount_RxBufferCheck == 0)?0:(ProfTime_RxBufferCheck.QuadPart / ProfCount_RxBufferCheck)));
   7.293 +    KdPrint((__DRIVER_NAME "     Linearize         Count = %10d, Avg Time = %10ld\n", ProfCount_Linearize, (ProfCount_Linearize == 0)?0:(ProfTime_Linearize.QuadPart / ProfCount_Linearize)));
   7.294 +    KdPrint((__DRIVER_NAME "     SendPackets       Count = %10d, Avg Time = %10ld\n", ProfCount_SendPackets, (ProfCount_SendPackets == 0)?0:(ProfTime_SendPackets.QuadPart / ProfCount_SendPackets)));
   7.295 +    KdPrint((__DRIVER_NAME "     SendQueuedPackets Count = %10d, Avg Time = %10ld\n", ProfCount_SendQueuedPackets, (ProfCount_SendQueuedPackets == 0)?0:(ProfTime_SendQueuedPackets.QuadPart / ProfCount_SendQueuedPackets)));
   7.296 +    KdPrint((__DRIVER_NAME "     GrantAccess       Count = %10d, Avg Time = %10ld\n", ProfCount_GrantAccess, (ProfCount_GrantAccess == 0)?0:(ProfTime_GrantAccess.QuadPart / ProfCount_GrantAccess)));
   7.297 +    KdPrint((__DRIVER_NAME "     EndAccess         Count = %10d, Avg Time = %10ld\n", ProfCount_EndAccess, (ProfCount_EndAccess == 0)?0:(ProfTime_EndAccess.QuadPart / ProfCount_EndAccess)));
   7.298 +  }
   7.299 +#endif
   7.300 +  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   7.301 +}
   7.302 +
   7.303 +static void
   7.304 +XenNet_TxBufferFree(struct xennet_info *xi)
   7.305 +{
   7.306 +  PLIST_ENTRY entry;
   7.307 +  PNDIS_PACKET packet;
   7.308 +  PMDL mdl;
   7.309 +  USHORT i;
   7.310 +
   7.311 +  ASSERT(!xi->connected);
   7.312 +
   7.313 +  /* Free packets in tx queue */
   7.314 +  entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   7.315 +  while (entry != &xi->tx_waiting_pkt_list)
   7.316 +  {
   7.317 +    packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   7.318 +    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   7.319 +    entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   7.320 +  }
   7.321 +
   7.322 +  /* free sent-but-not-completed packets */
   7.323 +  for (i = 0; i < NET_TX_RING_SIZE; i++)
   7.324 +  {
   7.325 +    packet = xi->tx_pkts[i];
   7.326 +    if (packet == NULL)
   7.327 +      continue;
   7.328 +
   7.329 +    mdl = *(PMDL *)packet->MiniportReservedEx;
   7.330 +    put_page_on_freelist(xi, mdl);
   7.331 +
   7.332 +    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   7.333 +  }
   7.334 +}
   7.335 +
   7.336 +BOOLEAN
   7.337 +XenNet_TxInit(xennet_info_t *xi)
   7.338 +{
   7.339 +  USHORT i;
   7.340 +
   7.341 +  xi->tx_mdl = AllocatePage();
   7.342 +  xi->tx_pgs = MmGetMdlVirtualAddress(xi->tx_mdl);
   7.343 +  SHARED_RING_INIT(xi->tx_pgs);
   7.344 +  FRONT_RING_INIT(&xi->tx, xi->tx_pgs, PAGE_SIZE);
   7.345 +  xi->tx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
   7.346 +    xi->XenInterface.InterfaceHeader.Context, 0,
   7.347 +    *MmGetMdlPfnArray(xi->tx_mdl), FALSE);
   7.348 +  xi->tx_id_free = 0;
   7.349 +  for (i = 0; i < NET_TX_RING_SIZE; i++)
   7.350 +  {
   7.351 +    xi->tx_pkts[i] = NULL;
   7.352 +    put_tx_id_on_freelist(xi, i);
   7.353 +  }
   7.354 +  return TRUE;
   7.355 +}
   7.356 +
   7.357 +BOOLEAN
   7.358 +XenNet_TxShutdown(xennet_info_t *xi)
   7.359 +{
   7.360 +  XenNet_TxBufferFree(xi);
   7.361 +  return TRUE;
   7.362 +}