win-pvdrivers

changeset 206:d841932ba7ae

Big rework of xennet to try and improve performance. Change the tx path to grant pages rather than copy them.
author James Harper <james.harper@bendigoit.com.au>
date Wed Mar 05 20:44:14 2008 +1100 (2008-03-05)
parents 3cc68cacff38
children 2b9e77dc2071
files common.inc common/include/public/io/netif.h common/include/xen_public.h xenenum/xenenum.c xenhide/xenhide.c xennet/xennet.c xennet/xennet.h xennet/xennet_rx.c xennet/xennet_tx.c xenpci/gnttbl.c xenpci/xenpci.c xenpci/xenpci.h xenscsi/xenscsi.c xenvbd/xenvbd.c
line diff
     1.1 --- a/common.inc	Sun Mar 02 22:13:49 2008 +1100
     1.2 +++ b/common.inc	Wed Mar 05 20:44:14 2008 +1100
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.4.46
     1.5 +VERSION=0.8.4.75
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7  KMDF_VERSION=1
     1.8  !IF $(_NT_TOOLS_VERSION) > 0x700
     2.1 --- a/common/include/public/io/netif.h	Sun Mar 02 22:13:49 2008 +1100
     2.2 +++ b/common/include/public/io/netif.h	Wed Mar 05 20:44:14 2008 +1100
     2.3 @@ -1,184 +1,184 @@
     2.4 -/******************************************************************************
     2.5 - * netif.h
     2.6 - * 
     2.7 - * Unified network-device I/O interface for Xen guest OSes.
     2.8 - * 
     2.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
    2.10 - * of this software and associated documentation files (the "Software"), to
    2.11 - * deal in the Software without restriction, including without limitation the
    2.12 - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    2.13 - * sell copies of the Software, and to permit persons to whom the Software is
    2.14 - * furnished to do so, subject to the following conditions:
    2.15 - *
    2.16 - * The above copyright notice and this permission notice shall be included in
    2.17 - * all copies or substantial portions of the Software.
    2.18 - *
    2.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    2.24 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    2.25 - * DEALINGS IN THE SOFTWARE.
    2.26 - *
    2.27 - * Copyright (c) 2003-2004, Keir Fraser
    2.28 - */
    2.29 -
    2.30 -#ifndef __XEN_PUBLIC_IO_NETIF_H__
    2.31 -#define __XEN_PUBLIC_IO_NETIF_H__
    2.32 -
    2.33 -#include "ring.h"
    2.34 -#include "../grant_table.h"
    2.35 -
    2.36 -/*
    2.37 - * Notifications after enqueuing any type of message should be conditional on
    2.38 - * the appropriate req_event or rsp_event field in the shared ring.
    2.39 - * If the client sends notification for rx requests then it should specify
    2.40 - * feature 'feature-rx-notify' via xenbus. Otherwise the backend will assume
    2.41 - * that it cannot safely queue packets (as it may not be kicked to send them).
    2.42 - */
    2.43 -
    2.44 -/*
    2.45 - * This is the 'wire' format for packets:
    2.46 - *  Request 1: netif_tx_request -- NETTXF_* (any flags)
    2.47 - * [Request 2: netif_tx_extra]  (only if request 1 has NETTXF_extra_info)
    2.48 - * [Request 3: netif_tx_extra]  (only if request 2 has XEN_NETIF_EXTRA_MORE)
    2.49 - *  Request 4: netif_tx_request -- NETTXF_more_data
    2.50 - *  Request 5: netif_tx_request -- NETTXF_more_data
    2.51 - *  ...
    2.52 - *  Request N: netif_tx_request -- 0
    2.53 - */
    2.54 -
    2.55 -/* Protocol checksum field is blank in the packet (hardware offload)? */
    2.56 -#define _NETTXF_csum_blank     (0)
    2.57 -#define  NETTXF_csum_blank     (1U<<_NETTXF_csum_blank)
    2.58 -
    2.59 -/* Packet data has been validated against protocol checksum. */
    2.60 -#define _NETTXF_data_validated (1)
    2.61 -#define  NETTXF_data_validated (1U<<_NETTXF_data_validated)
    2.62 -
    2.63 -/* Packet continues in the next request descriptor. */
    2.64 -#define _NETTXF_more_data      (2)
    2.65 -#define  NETTXF_more_data      (1U<<_NETTXF_more_data)
    2.66 -
    2.67 -/* Packet to be followed by extra descriptor(s). */
    2.68 -#define _NETTXF_extra_info     (3)
    2.69 -#define  NETTXF_extra_info     (1U<<_NETTXF_extra_info)
    2.70 -
    2.71 -struct netif_tx_request {
    2.72 -    grant_ref_t gref;      /* Reference to buffer page */
    2.73 -    uint16_t offset;       /* Offset within buffer page */
    2.74 -    uint16_t flags;        /* NETTXF_* */
    2.75 -    uint16_t id;           /* Echoed in response message. */
    2.76 -    uint16_t size;         /* Packet size in bytes.       */
    2.77 -};
    2.78 -typedef struct netif_tx_request netif_tx_request_t;
    2.79 -
    2.80 -/* Types of netif_extra_info descriptors. */
    2.81 -#define XEN_NETIF_EXTRA_TYPE_NONE  (0)  /* Never used - invalid */
    2.82 -#define XEN_NETIF_EXTRA_TYPE_GSO   (1)  /* u.gso */
    2.83 -#define XEN_NETIF_EXTRA_TYPE_MAX   (2)
    2.84 -
    2.85 -/* netif_extra_info flags. */
    2.86 -#define _XEN_NETIF_EXTRA_FLAG_MORE (0)
    2.87 -#define XEN_NETIF_EXTRA_FLAG_MORE  (1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
    2.88 -
    2.89 -/* GSO types - only TCPv4 currently supported. */
    2.90 -#define XEN_NETIF_GSO_TYPE_TCPV4        (1)
    2.91 -
    2.92 -/*
    2.93 - * This structure needs to fit within both netif_tx_request and
    2.94 - * netif_rx_response for compatibility.
    2.95 - */
    2.96 -struct netif_extra_info {
    2.97 -    uint8_t type;  /* XEN_NETIF_EXTRA_TYPE_* */
    2.98 -    uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
    2.99 -
   2.100 -    union {
   2.101 -        struct {
   2.102 -            /*
   2.103 -             * Maximum payload size of each segment. For example, for TCP this
   2.104 -             * is just the path MSS.
   2.105 -             */
   2.106 -            uint16_t size;
   2.107 -
   2.108 -            /*
   2.109 -             * GSO type. This determines the protocol of the packet and any
   2.110 -             * extra features required to segment the packet properly.
   2.111 -             */
   2.112 -            uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
   2.113 -
   2.114 -            /* Future expansion. */
   2.115 -            uint8_t pad;
   2.116 -
   2.117 -            /*
   2.118 -             * GSO features. This specifies any extra GSO features required
   2.119 -             * to process this packet, such as ECN support for TCPv4.
   2.120 -             */
   2.121 -            uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
   2.122 -        } gso;
   2.123 -
   2.124 -        uint16_t pad[3];
   2.125 -    } u;
   2.126 -};
   2.127 -
   2.128 -struct netif_tx_response {
   2.129 -    uint16_t id;
   2.130 -    int16_t  status;       /* NETIF_RSP_* */
   2.131 -};
   2.132 -typedef struct netif_tx_response netif_tx_response_t;
   2.133 -
   2.134 -struct netif_rx_request {
   2.135 -    uint16_t    id;        /* Echoed in response message.        */
   2.136 -    grant_ref_t gref;      /* Reference to incoming granted frame */
   2.137 -};
   2.138 -typedef struct netif_rx_request netif_rx_request_t;
   2.139 -
   2.140 -/* Packet data has been validated against protocol checksum. */
   2.141 -#define _NETRXF_data_validated (0)
   2.142 -#define  NETRXF_data_validated (1U<<_NETRXF_data_validated)
   2.143 -
   2.144 -/* Protocol checksum field is blank in the packet (hardware offload)? */
   2.145 -#define _NETRXF_csum_blank     (1)
   2.146 -#define  NETRXF_csum_blank     (1U<<_NETRXF_csum_blank)
   2.147 -
   2.148 -/* Packet continues in the next request descriptor. */
   2.149 -#define _NETRXF_more_data      (2)
   2.150 -#define  NETRXF_more_data      (1U<<_NETRXF_more_data)
   2.151 -
   2.152 -/* Packet to be followed by extra descriptor(s). */
   2.153 -#define _NETRXF_extra_info     (3)
   2.154 -#define  NETRXF_extra_info     (1U<<_NETRXF_extra_info)
   2.155 -
   2.156 -struct netif_rx_response {
   2.157 -    uint16_t id;
   2.158 -    uint16_t offset;       /* Offset in page of start of received packet  */
   2.159 -    uint16_t flags;        /* NETRXF_* */
   2.160 -    int16_t  status;       /* -ve: NETIF_RSP_* ; +ve: Rx'ed pkt size. */
   2.161 -};
   2.162 -typedef struct netif_rx_response netif_rx_response_t;
   2.163 -
   2.164 -/*
   2.165 - * Generate netif ring structures and types.
   2.166 - */
   2.167 -
   2.168 -DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
   2.169 -DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
   2.170 -
   2.171 -#define NETIF_RSP_DROPPED         -2
   2.172 -#define NETIF_RSP_ERROR           -1
   2.173 -#define NETIF_RSP_OKAY             0
   2.174 -/* No response: used for auxiliary requests (e.g., netif_tx_extra). */
   2.175 -#define NETIF_RSP_NULL             1
   2.176 -
   2.177 -#endif
   2.178 -
   2.179 -/*
   2.180 - * Local variables:
   2.181 - * mode: C
   2.182 - * c-set-style: "BSD"
   2.183 - * c-basic-offset: 4
   2.184 - * tab-width: 4
   2.185 - * indent-tabs-mode: nil
   2.186 - * End:
   2.187 - */
   2.188 +/******************************************************************************
   2.189 + * netif.h
   2.190 + * 
   2.191 + * Unified network-device I/O interface for Xen guest OSes.
   2.192 + * 
   2.193 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   2.194 + * of this software and associated documentation files (the "Software"), to
   2.195 + * deal in the Software without restriction, including without limitation the
   2.196 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   2.197 + * sell copies of the Software, and to permit persons to whom the Software is
   2.198 + * furnished to do so, subject to the following conditions:
   2.199 + *
   2.200 + * The above copyright notice and this permission notice shall be included in
   2.201 + * all copies or substantial portions of the Software.
   2.202 + *
   2.203 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   2.204 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   2.205 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   2.206 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   2.207 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   2.208 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   2.209 + * DEALINGS IN THE SOFTWARE.
   2.210 + *
   2.211 + * Copyright (c) 2003-2004, Keir Fraser
   2.212 + */
   2.213 +
   2.214 +#ifndef __XEN_PUBLIC_IO_NETIF_H__
   2.215 +#define __XEN_PUBLIC_IO_NETIF_H__
   2.216 +
   2.217 +#include "ring.h"
   2.218 +#include "../grant_table.h"
   2.219 +
   2.220 +/*
   2.221 + * Notifications after enqueuing any type of message should be conditional on
   2.222 + * the appropriate req_event or rsp_event field in the shared ring.
   2.223 + * If the client sends notification for rx requests then it should specify
   2.224 + * feature 'feature-rx-notify' via xenbus. Otherwise the backend will assume
   2.225 + * that it cannot safely queue packets (as it may not be kicked to send them).
   2.226 + */
   2.227 +
   2.228 +/*
   2.229 + * This is the 'wire' format for packets:
   2.230 + *  Request 1: netif_tx_request -- NETTXF_* (any flags)
   2.231 + * [Request 2: netif_tx_extra]  (only if request 1 has NETTXF_extra_info)
   2.232 + * [Request 3: netif_tx_extra]  (only if request 2 has XEN_NETIF_EXTRA_MORE)
   2.233 + *  Request 4: netif_tx_request -- NETTXF_more_data
   2.234 + *  Request 5: netif_tx_request -- NETTXF_more_data
   2.235 + *  ...
   2.236 + *  Request N: netif_tx_request -- 0
   2.237 + */
   2.238 +
   2.239 +/* Protocol checksum field is blank in the packet (hardware offload)? */
   2.240 +#define _NETTXF_csum_blank     (0)
   2.241 +#define  NETTXF_csum_blank     (1U<<_NETTXF_csum_blank)
   2.242 +
   2.243 +/* Packet data has been validated against protocol checksum. */
   2.244 +#define _NETTXF_data_validated (1)
   2.245 +#define  NETTXF_data_validated (1U<<_NETTXF_data_validated)
   2.246 +
   2.247 +/* Packet continues in the next request descriptor. */
   2.248 +#define _NETTXF_more_data      (2)
   2.249 +#define  NETTXF_more_data      (1U<<_NETTXF_more_data)
   2.250 +
   2.251 +/* Packet to be followed by extra descriptor(s). */
   2.252 +#define _NETTXF_extra_info     (3)
   2.253 +#define  NETTXF_extra_info     (1U<<_NETTXF_extra_info)
   2.254 +
   2.255 +struct netif_tx_request {
   2.256 +    grant_ref_t gref;      /* Reference to buffer page */
   2.257 +    uint16_t offset;       /* Offset within buffer page */
   2.258 +    uint16_t flags;        /* NETTXF_* */
   2.259 +    uint16_t id;           /* Echoed in response message. */
   2.260 +    uint16_t size;         /* Packet size in bytes.       */
   2.261 +};
   2.262 +typedef struct netif_tx_request netif_tx_request_t;
   2.263 +
   2.264 +/* Types of netif_extra_info descriptors. */
   2.265 +#define XEN_NETIF_EXTRA_TYPE_NONE  (0)  /* Never used - invalid */
   2.266 +#define XEN_NETIF_EXTRA_TYPE_GSO   (1)  /* u.gso */
   2.267 +#define XEN_NETIF_EXTRA_TYPE_MAX   (2)
   2.268 +
   2.269 +/* netif_extra_info flags. */
   2.270 +#define _XEN_NETIF_EXTRA_FLAG_MORE (0)
   2.271 +#define XEN_NETIF_EXTRA_FLAG_MORE  (1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
   2.272 +
   2.273 +/* GSO types - only TCPv4 currently supported. */
   2.274 +#define XEN_NETIF_GSO_TYPE_TCPV4        (1)
   2.275 +
   2.276 +/*
   2.277 + * This structure needs to fit within both netif_tx_request and
   2.278 + * netif_rx_response for compatibility.
   2.279 + */
   2.280 +struct netif_extra_info {
   2.281 +    uint8_t type;  /* XEN_NETIF_EXTRA_TYPE_* */
   2.282 +    uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
   2.283 +
   2.284 +    union {
   2.285 +        struct {
   2.286 +            /*
   2.287 +             * Maximum payload size of each segment. For example, for TCP this
   2.288 +             * is just the path MSS.
   2.289 +             */
   2.290 +            uint16_t size;
   2.291 +
   2.292 +            /*
   2.293 +             * GSO type. This determines the protocol of the packet and any
   2.294 +             * extra features required to segment the packet properly.
   2.295 +             */
   2.296 +            uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
   2.297 +
   2.298 +            /* Future expansion. */
   2.299 +            uint8_t pad;
   2.300 +
   2.301 +            /*
   2.302 +             * GSO features. This specifies any extra GSO features required
   2.303 +             * to process this packet, such as ECN support for TCPv4.
   2.304 +             */
   2.305 +            uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
   2.306 +        } gso;
   2.307 +
   2.308 +        uint16_t pad[3];
   2.309 +    } u;
   2.310 +};
   2.311 +
   2.312 +struct netif_tx_response {
   2.313 +    uint16_t id;
   2.314 +    int16_t  status;       /* NETIF_RSP_* */
   2.315 +};
   2.316 +typedef struct netif_tx_response netif_tx_response_t;
   2.317 +
   2.318 +struct netif_rx_request {
   2.319 +    uint16_t    id;        /* Echoed in response message.        */
   2.320 +    grant_ref_t gref;      /* Reference to incoming granted frame */
   2.321 +};
   2.322 +typedef struct netif_rx_request netif_rx_request_t;
   2.323 +
   2.324 +/* Packet data has been validated against protocol checksum. */
   2.325 +#define _NETRXF_data_validated (0)
   2.326 +#define  NETRXF_data_validated (1U<<_NETRXF_data_validated)
   2.327 +
   2.328 +/* Protocol checksum field is blank in the packet (hardware offload)? */
   2.329 +#define _NETRXF_csum_blank     (1)
   2.330 +#define  NETRXF_csum_blank     (1U<<_NETRXF_csum_blank)
   2.331 +
   2.332 +/* Packet continues in the next request descriptor. */
   2.333 +#define _NETRXF_more_data      (2)
   2.334 +#define  NETRXF_more_data      (1U<<_NETRXF_more_data)
   2.335 +
   2.336 +/* Packet to be followed by extra descriptor(s). */
   2.337 +#define _NETRXF_extra_info     (3)
   2.338 +#define  NETRXF_extra_info     (1U<<_NETRXF_extra_info)
   2.339 +
   2.340 +struct netif_rx_response {
   2.341 +    uint16_t id;
   2.342 +    uint16_t offset;       /* Offset in page of start of received packet  */
   2.343 +    uint16_t flags;        /* NETRXF_* */
   2.344 +    int16_t  status;       /* -ve: NETIF_RSP_* ; +ve: Rx'ed pkt size. */
   2.345 +};
   2.346 +typedef struct netif_rx_response netif_rx_response_t;
   2.347 +
   2.348 +/*
   2.349 + * Generate netif ring structures and types.
   2.350 + */
   2.351 +
   2.352 +DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
   2.353 +DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
   2.354 +
   2.355 +#define NETIF_RSP_DROPPED         -2
   2.356 +#define NETIF_RSP_ERROR           -1
   2.357 +#define NETIF_RSP_OKAY             0
   2.358 +/* No response: used for auxiliary requests (e.g., netif_tx_extra). */
   2.359 +#define NETIF_RSP_NULL             1
   2.360 +
   2.361 +#endif
   2.362 +
   2.363 +/*
   2.364 + * Local variables:
   2.365 + * mode: C
   2.366 + * c-set-style: "BSD"
   2.367 + * c-basic-offset: 4
   2.368 + * tab-width: 4
   2.369 + * indent-tabs-mode: nil
   2.370 + * End:
   2.371 + */
   2.372 \ No newline at end of file
     3.1 --- a/common/include/xen_public.h	Sun Mar 02 22:13:49 2008 +1100
     3.2 +++ b/common/include/xen_public.h	Wed Mar 05 20:44:14 2008 +1100
     3.3 @@ -51,9 +51,17 @@ typedef evtchn_port_t
     3.4  (*PXEN_EVTCHN_ALLOCUNBOUND)(PVOID Context, domid_t Domain);
     3.5  
     3.6  typedef grant_ref_t
     3.7 -(*PXEN_GNTTBL_GRANTACCESS)(WDFDEVICE Device, domid_t domid, uint32_t frame, int readonly);
     3.8 +(*PXEN_GNTTBL_GRANTACCESS)(WDFDEVICE Device, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref);
     3.9 +
    3.10  typedef BOOLEAN
    3.11 -(*PXEN_GNTTBL_ENDACCESS)(WDFDEVICE Device, grant_ref_t ref);
    3.12 +(*PXEN_GNTTBL_ENDACCESS)(WDFDEVICE Device, grant_ref_t ref, BOOLEAN keepref);
    3.13 +
    3.14 +typedef VOID
    3.15 +(*PXEN_GNTTBL_PUTREF)(WDFDEVICE Device, grant_ref_t ref);
    3.16 +
    3.17 +typedef grant_ref_t
    3.18 +(*PXEN_GNTTBL_GETREF)(WDFDEVICE Device);
    3.19 +
    3.20  
    3.21  typedef VOID
    3.22  (*PXENBUS_WATCH_CALLBACK)(char *Path, PVOID ServiceContext);
    3.23 @@ -96,6 +104,8 @@ typedef struct _XEN_IFACE {
    3.24    PXEN_EVTCHN_ALLOCUNBOUND EvtChn_AllocUnbound;
    3.25    PXEN_EVTCHN_BIND EvtChn_BindDpc;
    3.26  
    3.27 +  PXEN_GNTTBL_GETREF GntTbl_GetRef;
    3.28 +  PXEN_GNTTBL_PUTREF GntTbl_PutRef;
    3.29    PXEN_GNTTBL_GRANTACCESS GntTbl_GrantAccess;
    3.30    PXEN_GNTTBL_ENDACCESS GntTbl_EndAccess;
    3.31  
     4.1 --- a/xenenum/xenenum.c	Sun Mar 02 22:13:49 2008 +1100
     4.2 +++ b/xenenum/xenenum.c	Wed Mar 05 20:44:14 2008 +1100
     4.3 @@ -150,7 +150,7 @@ XenEnum_PrepareHardware(
     4.4  
     4.5    KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
     4.6  
     4.7 -  status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE, (PINTERFACE)&xedd->XenInterface, sizeof(XEN_IFACE), 1, NULL);
     4.8 +  status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE, (PINTERFACE)&xedd->XenInterface, sizeof(XEN_IFACE), 2, NULL);
     4.9    if(!NT_SUCCESS(status))
    4.10    {
    4.11      KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
    4.12 @@ -442,7 +442,7 @@ XenEnum_ChildListCreateDevice(WDFCHILDLI
    4.13    strncpy(ChildDeviceData->Path, XenIdentificationDesc->Path, 128);
    4.14    
    4.15    ChildDeviceData->XenInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->XenInterface);
    4.16 -  ChildDeviceData->XenInterface.InterfaceHeader.Version = 1;
    4.17 +  ChildDeviceData->XenInterface.InterfaceHeader.Version = 2;
    4.18    ChildDeviceData->XenInterface.InterfaceHeader.Context = xedd->XenInterface.InterfaceHeader.Context;
    4.19    ChildDeviceData->XenInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
    4.20    ChildDeviceData->XenInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
    4.21 @@ -458,6 +458,8 @@ XenEnum_ChildListCreateDevice(WDFCHILDLI
    4.22    ChildDeviceData->XenInterface.EvtChn_AllocUnbound = xedd->XenInterface.EvtChn_AllocUnbound;
    4.23    ChildDeviceData->XenInterface.EvtChn_BindDpc = xedd->XenInterface.EvtChn_BindDpc;
    4.24  
    4.25 +  ChildDeviceData->XenInterface.GntTbl_GetRef = xedd->XenInterface.GntTbl_GetRef;
    4.26 +  ChildDeviceData->XenInterface.GntTbl_PutRef = xedd->XenInterface.GntTbl_PutRef;
    4.27    ChildDeviceData->XenInterface.GntTbl_GrantAccess = xedd->XenInterface.GntTbl_GrantAccess;
    4.28    ChildDeviceData->XenInterface.GntTbl_EndAccess = xedd->XenInterface.GntTbl_EndAccess;
    4.29  
     5.1 --- a/xenhide/xenhide.c	Sun Mar 02 22:13:49 2008 +1100
     5.2 +++ b/xenhide/xenhide.c	Wed Mar 05 20:44:14 2008 +1100
     5.3 @@ -257,6 +257,7 @@ XenHide_IoCompletion(PDEVICE_OBJECT Devi
     5.4    size_t StrLen;
     5.5    int Match;
     5.6    int Offset = 0;
     5.7 +  int FoundIde = 0;
     5.8    PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)Context;
     5.9  
    5.10    UNREFERENCED_PARAMETER(DeviceObject);
    5.11 @@ -292,9 +293,10 @@ XenHide_IoCompletion(PDEVICE_OBJECT Devi
    5.12             StrLen = 0;
    5.13            for (Ptr = Buffer; *Ptr != 0; Ptr += StrLen + 1)
    5.14            {
    5.15 -            // Qemu PCI
    5.16 +            // Qemu IDE
    5.17              if (XenHide_StringMatches(Ptr, L"PCI\\VEN_8086&DEV_7010")) {
    5.18                Match = 1;
    5.19 +              FoundIde = 1;
    5.20                break;
    5.21              }
    5.22              // Qemu Network
    5.23 @@ -310,12 +312,21 @@ XenHide_IoCompletion(PDEVICE_OBJECT Devi
    5.24            Offset++;
    5.25          }
    5.26        }
    5.27 +      if (!FoundIde)
    5.28 +      {
    5.29 +        /*
    5.30 +        We _must_ not let windows continue if the PV drivers have been
    5.31 +        activated and we haven't managed to find and hide the IDE device.
    5.32 +        Throwing a BSoD is the only option at this point.
    5.33 +        */
    5.34 +        KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000002, 0x00000000, 0x00000000, 0x00000000);
    5.35 +      }
    5.36        Relations->Count -= Offset;
    5.37 -      break;
    5.38 -    default:
    5.39 -      break;
    5.40      }
    5.41 -  }    
    5.42 +    break;
    5.43 +  default:
    5.44 +    break;
    5.45 +  }
    5.46  //  KdPrint((__DRIVER_NAME " <-- IoCompletion\n"));
    5.47  
    5.48    return Irp->IoStatus.Status;
     6.1 --- a/xennet/xennet.c	Sun Mar 02 22:13:49 2008 +1100
     6.2 +++ b/xennet/xennet.c	Wed Mar 05 20:44:14 2008 +1100
     6.3 @@ -23,28 +23,21 @@ Foundation, Inc., 51 Franklin Street, Fi
     6.4  #include "xennet.h"
     6.5  
     6.6  LARGE_INTEGER ProfTime_TxBufferGC;
     6.7 -LARGE_INTEGER ProfTime_TxBufferFree;
     6.8  LARGE_INTEGER ProfTime_RxBufferAlloc;
     6.9 -LARGE_INTEGER ProfTime_RxBufferFree;
    6.10  LARGE_INTEGER ProfTime_ReturnPacket;
    6.11  LARGE_INTEGER ProfTime_RxBufferCheck;
    6.12  LARGE_INTEGER ProfTime_Linearize;
    6.13  LARGE_INTEGER ProfTime_SendPackets;
    6.14  LARGE_INTEGER ProfTime_SendQueuedPackets;
    6.15 -LARGE_INTEGER ProfTime_GrantAccess;
    6.16 -LARGE_INTEGER ProfTime_EndAccess;
    6.17  
    6.18  int ProfCount_TxBufferGC;
    6.19 -int ProfCount_TxBufferFree;
    6.20  int ProfCount_RxBufferAlloc;
    6.21 -int ProfCount_RxBufferFree;
    6.22  int ProfCount_ReturnPacket;
    6.23  int ProfCount_RxBufferCheck;
    6.24  int ProfCount_Linearize;
    6.25  int ProfCount_SendPackets;
    6.26 +int ProfCount_PacketsPerSendPackets;
    6.27  int ProfCount_SendQueuedPackets;
    6.28 -int ProfCount_GrantAccess;
    6.29 -int ProfCount_EndAccess;
    6.30  
    6.31  int ProfCount_TxPacketsTotal;
    6.32  int ProfCount_TxPacketsOffload;
    6.33 @@ -81,74 +74,6 @@ simple_strtoul(const char *cp,char **end
    6.34    return result;
    6.35  }
    6.36  
    6.37 -PMDL
    6.38 -get_page_from_freelist(struct xennet_info *xi)
    6.39 -{
    6.40 -  PMDL mdl;
    6.41 -  KIRQL OldIrql;
    6.42 -
    6.43 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    6.44 -
    6.45 -  KeAcquireSpinLock(&xi->page_lock, &OldIrql);
    6.46 -
    6.47 -  if (xi->page_free == 0)
    6.48 -  {
    6.49 -    mdl = AllocatePagesExtra(1, sizeof(grant_ref_t));
    6.50 -    *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)) = xi->XenInterface.GntTbl_GrantAccess(
    6.51 -      xi->XenInterface.InterfaceHeader.Context, 0,
    6.52 -      *MmGetMdlPfnArray(mdl), FALSE);
    6.53 -//    KdPrint(("New Mdl = %p, MmGetMdlVirtualAddress = %p, MmGetSystemAddressForMdlSafe = %p\n",
    6.54 -//      mdl, MmGetMdlVirtualAddress(mdl), MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority)));
    6.55 -  }
    6.56 -  else
    6.57 -  {
    6.58 -    xi->page_free--;
    6.59 -    mdl = xi->page_list[xi->page_free];
    6.60 -//    KdPrint(("Old Mdl = %p, MmGetMdlVirtualAddress = %p, MmGetSystemAddressForMdlSafe = %p\n",
    6.61 -//      mdl, MmGetMdlVirtualAddress(mdl), MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority)));
    6.62 -  }
    6.63 -  KeReleaseSpinLock(&xi->page_lock, OldIrql);
    6.64 -
    6.65 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    6.66 -
    6.67 -  return mdl;
    6.68 -}
    6.69 -
    6.70 -VOID
    6.71 -free_page_freelist(struct xennet_info *xi)
    6.72 -{
    6.73 -  PMDL mdl;
    6.74 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    6.75 -
    6.76 -  while(xi->page_free != 0)
    6.77 -  {
    6.78 -    xi->page_free--;
    6.79 -    mdl = xi->page_list[xi->page_free];
    6.80 -    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
    6.81 -      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)));
    6.82 -    FreePages(mdl);
    6.83 -  }
    6.84 -}
    6.85 -
    6.86 -VOID
    6.87 -put_page_on_freelist(struct xennet_info *xi, PMDL mdl)
    6.88 -{
    6.89 -  KIRQL OldIrql;
    6.90 -
    6.91 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    6.92 -
    6.93 -//  KdPrint(("Mdl = %p\n",  mdl));
    6.94 -
    6.95 -  KeAcquireSpinLock(&xi->page_lock, &OldIrql);
    6.96 -
    6.97 -  xi->page_list[xi->page_free] = mdl;
    6.98 -  xi->page_free++;
    6.99 -
   6.100 -  KeReleaseSpinLock(&xi->page_lock, OldIrql);
   6.101 -
   6.102 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.103 -}
   6.104 -
   6.105  // Called at DISPATCH_LEVEL
   6.106  
   6.107  static BOOLEAN
   6.108 @@ -329,9 +254,6 @@ XenNet_Init(
   6.109  
   6.110    InitializeListHead(&xi->tx_waiting_pkt_list);
   6.111  
   6.112 -  KeInitializeSpinLock(&xi->page_lock);
   6.113 -  xi->page_free = 0;
   6.114 -  
   6.115    NdisAllocatePacketPool(&status, &xi->packet_pool, XN_RX_QUEUE_LEN,
   6.116      PROTOCOL_RESERVED_SIZE_IN_PACKET);
   6.117    if (status != NDIS_STATUS_SUCCESS)
   6.118 @@ -366,9 +288,17 @@ XenNet_Init(
   6.119    }
   6.120  
   6.121    NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
   6.122 -    0, (NDIS_ATTRIBUTE_DESERIALIZE /*| NDIS_ATTRIBUTE_BUS_MASTER*/),
   6.123 +    0, (NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_BUS_MASTER),
   6.124      NdisInterfaceInternal);
   6.125  
   6.126 +  status = NdisMInitializeScatterGatherDma(xi->adapter_handle, TRUE, XN_MAX_PKT_SIZE);
   6.127 +  if (!NT_SUCCESS(status))
   6.128 +  {
   6.129 +    KdPrint(("NdisMInitializeScatterGatherDma failed with 0x%x\n", status));
   6.130 +    status = NDIS_STATUS_FAILURE;
   6.131 +    goto err;
   6.132 +  }
   6.133 +
   6.134    WDF_OBJECT_ATTRIBUTES_INIT(&wdf_attrs);
   6.135  
   6.136    status = WdfDeviceMiniportCreate(WdfGetDriver(), &wdf_attrs, xi->fdo,
   6.137 @@ -383,7 +313,7 @@ XenNet_Init(
   6.138    /* get lower (Xen) interfaces */
   6.139  
   6.140    status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE,
   6.141 -    (PINTERFACE) &xi->XenInterface, sizeof(XEN_IFACE), 1, NULL);
   6.142 +    (PINTERFACE) &xi->XenInterface, sizeof(XEN_IFACE), 2, NULL);
   6.143    if(!NT_SUCCESS(status))
   6.144    {
   6.145      KdPrint(("WdfFdoQueryForInterface failed with status 0x%08x\n", status));
   6.146 @@ -598,35 +528,11 @@ XenNet_Halt(
   6.147    xi->connected = FALSE;
   6.148    KeMemoryBarrier(); /* make sure everyone sees that we are now shut down */
   6.149  
   6.150 -  /* wait for all receive buffers to be returned */
   6.151 -  while (xi->rx_outstanding > 0)
   6.152 -    KeWaitForSingleObject(&xi->shutdown_event, Executive, KernelMode, FALSE, NULL);
   6.153 -
   6.154    // TODO: remove event channel xenbus entry (how?)
   6.155  
   6.156 -  /* free TX resources */
   6.157 -  if (xi->XenInterface.GntTbl_EndAccess(if_cxt, xi->tx_ring_ref))
   6.158 -  {
   6.159 -    xi->tx_ring_ref = GRANT_INVALID_REF;
   6.160 -    FreePages(xi->tx_mdl);
   6.161 -  }
   6.162 -  /* if EndAccess fails then tx/rx ring pages LEAKED -- it's not safe to reuse
   6.163 -     pages Dom0 still has access to */
   6.164 -  xi->tx_pgs = NULL;
   6.165 -
   6.166 -  /* free RX resources */
   6.167 -  if (xi->XenInterface.GntTbl_EndAccess(if_cxt, xi->rx_ring_ref))
   6.168 -  {
   6.169 -    xi->rx_ring_ref = GRANT_INVALID_REF;
   6.170 -    FreePages(xi->rx_mdl);
   6.171 -  }
   6.172 -  xi->rx_pgs = NULL;
   6.173 -
   6.174    XenNet_TxShutdown(xi);
   6.175    XenNet_RxShutdown(xi);
   6.176  
   6.177 -  free_page_freelist(xi);
   6.178 -
   6.179    /* Remove watch on backend state */
   6.180    RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->backend_path);
   6.181    xi->XenInterface.XenBus_RemWatch(if_cxt, XBT_NIL, TmpPath,
   6.182 @@ -669,28 +575,21 @@ DriverEntry(
   6.183  
   6.184  
   6.185    ProfTime_TxBufferGC.QuadPart = 0;
   6.186 -  ProfTime_TxBufferFree.QuadPart = 0;
   6.187    ProfTime_RxBufferAlloc.QuadPart = 0;
   6.188 -  ProfTime_RxBufferFree.QuadPart = 0;
   6.189    ProfTime_ReturnPacket.QuadPart = 0;
   6.190    ProfTime_RxBufferCheck.QuadPart = 0;
   6.191    ProfTime_Linearize.QuadPart = 0;
   6.192    ProfTime_SendPackets.QuadPart = 0;
   6.193    ProfTime_SendQueuedPackets.QuadPart = 0;
   6.194 -  ProfTime_GrantAccess.QuadPart = 0;
   6.195 -  ProfTime_EndAccess.QuadPart = 0;
   6.196  
   6.197    ProfCount_TxBufferGC = 0;
   6.198 -  ProfCount_TxBufferFree = 0;
   6.199    ProfCount_RxBufferAlloc = 0;
   6.200 -  ProfCount_RxBufferFree = 0;
   6.201    ProfCount_ReturnPacket = 0;
   6.202    ProfCount_RxBufferCheck = 0;
   6.203    ProfCount_Linearize = 0;
   6.204    ProfCount_SendPackets = 0;
   6.205 +  ProfCount_PacketsPerSendPackets = 0;
   6.206    ProfCount_SendQueuedPackets = 0;
   6.207 -  ProfCount_GrantAccess = 0;
   6.208 -  ProfCount_EndAccess = 0;
   6.209  
   6.210    ProfCount_TxPacketsTotal = 0;
   6.211    ProfCount_TxPacketsOffload = 0;
     7.1 --- a/xennet/xennet.h	Sun Mar 02 22:13:49 2008 +1100
     7.2 +++ b/xennet/xennet.h	Wed Mar 05 20:44:14 2008 +1100
     7.3 @@ -72,7 +72,7 @@ Foundation, Inc., 51 Franklin Street, Fi
     7.4  
     7.5  #pragma warning(disable: 4127) // conditional expression is constant
     7.6  
     7.7 -#define XEN_PROFILE
     7.8 +//#define XEN_PROFILE
     7.9  
    7.10  /* TODO: crank this up if we support higher mtus? */
    7.11  #define XN_DATA_SIZE 1500
    7.12 @@ -125,9 +125,12 @@ struct xennet_info
    7.13    grant_ref_t tx_ring_ref;
    7.14    struct netif_tx_sring *tx_pgs;
    7.15    PMDL tx_mdl;
    7.16 +  ULONG tx_id_free;
    7.17    USHORT tx_id_list[NET_TX_RING_SIZE];
    7.18 -  ULONG tx_id_free;
    7.19 +  ULONG tx_gref_free;
    7.20 +  grant_ref_t tx_gref_list[NET_TX_RING_SIZE];
    7.21    PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE];
    7.22 +  grant_ref_t tx_grefs[NET_TX_RING_SIZE];
    7.23  
    7.24    /* rx_related - protected by rx_lock */
    7.25    struct netif_rx_front_ring rx;
    7.26 @@ -137,11 +140,8 @@ struct xennet_info
    7.27    USHORT rx_id_list[NET_RX_RING_SIZE];
    7.28    ULONG rx_id_free;
    7.29    PNDIS_BUFFER rx_buffers[NET_RX_RING_SIZE];
    7.30 -
    7.31 -  /* id list - protected by page_lock */
    7.32 -  PMDL page_list[NET_TX_RING_SIZE + NET_RX_RING_SIZE];
    7.33 +  PMDL page_list[NET_RX_RING_SIZE];
    7.34    ULONG page_free;
    7.35 -  KSPIN_LOCK page_lock;
    7.36  
    7.37    /* Receive-ring batched refills. */
    7.38  #define RX_MIN_TARGET 8
    7.39 @@ -182,6 +182,7 @@ extern int ProfCount_ReturnPacket;
    7.40  extern int ProfCount_RxBufferCheck;
    7.41  extern int ProfCount_Linearize;
    7.42  extern int ProfCount_SendPackets;
    7.43 +extern int ProfCount_PacketsPerSendPackets;
    7.44  extern int ProfCount_SendQueuedPackets;
    7.45  
    7.46  extern int ProfCount_TxPacketsTotal;
    7.47 @@ -238,15 +239,3 @@ XenNet_SetInformation(
    7.48    OUT PULONG BytesRead,
    7.49    OUT PULONG BytesNeeded
    7.50    );
    7.51 -
    7.52 -static __inline grant_ref_t
    7.53 -get_grant_ref(PMDL mdl)
    7.54 -{
    7.55 -  return *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE));
    7.56 -}
    7.57 -
    7.58 -VOID
    7.59 -put_page_on_freelist(struct xennet_info *xi, PMDL mdl);
    7.60 -
    7.61 -PMDL
    7.62 -get_page_from_freelist(struct xennet_info *xi);
     8.1 --- a/xennet/xennet_rx.c	Sun Mar 02 22:13:49 2008 +1100
     8.2 +++ b/xennet/xennet_rx.c	Wed Mar 05 20:44:14 2008 +1100
     8.3 @@ -36,6 +36,70 @@ put_rx_id_on_freelist(struct xennet_info
     8.4    xi->rx_id_free++;
     8.5  }
     8.6  
     8.7 +static PMDL
     8.8 +get_page_from_freelist(struct xennet_info *xi)
     8.9 +{
    8.10 +  PMDL mdl;
    8.11 +
    8.12 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    8.13 +
    8.14 +  if (xi->page_free == 0)
    8.15 +  {
    8.16 +    mdl = AllocatePagesExtra(1, sizeof(grant_ref_t));
    8.17 +    *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)) = xi->XenInterface.GntTbl_GrantAccess(
    8.18 +      xi->XenInterface.InterfaceHeader.Context, 0,
    8.19 +      *MmGetMdlPfnArray(mdl), FALSE, 0);
    8.20 +//    KdPrint(("New Mdl = %p, MmGetMdlVirtualAddress = %p, MmGetSystemAddressForMdlSafe = %p\n",
    8.21 +//      mdl, MmGetMdlVirtualAddress(mdl), MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority)));
    8.22 +  }
    8.23 +  else
    8.24 +  {
    8.25 +    xi->page_free--;
    8.26 +    mdl = xi->page_list[xi->page_free];
    8.27 +//    KdPrint(("Old Mdl = %p, MmGetMdlVirtualAddress = %p, MmGetSystemAddressForMdlSafe = %p\n",
    8.28 +//      mdl, MmGetMdlVirtualAddress(mdl), MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority)));
    8.29 +  }
    8.30 +
    8.31 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    8.32 +
    8.33 +  return mdl;
    8.34 +}
    8.35 +
    8.36 +static VOID
    8.37 +free_page_freelist(struct xennet_info *xi)
    8.38 +{
    8.39 +  PMDL mdl;
    8.40 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    8.41 +
    8.42 +  while(xi->page_free != 0)
    8.43 +  {
    8.44 +    xi->page_free--;
    8.45 +    mdl = xi->page_list[xi->page_free];
    8.46 +    xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
    8.47 +      *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE)), 0);
    8.48 +    FreePages(mdl);
    8.49 +  }
    8.50 +}
    8.51 +
    8.52 +static VOID
    8.53 +put_page_on_freelist(struct xennet_info *xi, PMDL mdl)
    8.54 +{
    8.55 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    8.56 +
    8.57 +//  KdPrint(("Mdl = %p\n",  mdl));
    8.58 +
    8.59 +  xi->page_list[xi->page_free] = mdl;
    8.60 +  xi->page_free++;
    8.61 +
    8.62 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    8.63 +}
    8.64 +
    8.65 +static __inline grant_ref_t
    8.66 +get_grant_ref(PMDL mdl)
    8.67 +{
    8.68 +  return *(grant_ref_t *)(((UCHAR *)mdl) + MmSizeOfMdl(0, PAGE_SIZE));
    8.69 +}
    8.70 +
    8.71  // Called at DISPATCH_LEVEL with rx lock held
    8.72  static NDIS_STATUS
    8.73  XenNet_RxBufferAlloc(struct xennet_info *xi)
    8.74 @@ -104,11 +168,9 @@ XenNet_RxBufferCheck(struct xennet_info 
    8.75    ULONG packet_count;
    8.76    PMDL mdl;
    8.77    int moretodo;
    8.78 -  KIRQL OldIrql;
    8.79    struct netif_rx_response *rxrsp = NULL;
    8.80    int more_frags = 0;
    8.81    NDIS_STATUS status;
    8.82 -  LARGE_INTEGER time_received;
    8.83    USHORT id;
    8.84    PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    8.85  #if defined(XEN_PROFILE)
    8.86 @@ -123,8 +185,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    8.87  
    8.88    ASSERT(xi->connected);
    8.89  
    8.90 -  NdisGetCurrentSystemTime(&time_received);
    8.91 -  KeAcquireSpinLock(&xi->rx_lock, &OldIrql);
    8.92 +  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
    8.93  
    8.94    packet_count = 0;
    8.95    do {
    8.96 @@ -176,12 +237,11 @@ XenNet_RxBufferCheck(struct xennet_info 
    8.97          ProfCount_RxPacketsTotal++;
    8.98  #endif
    8.99          xi->stat_rx_ok++;
   8.100 -        InterlockedIncrement(&xi->rx_outstanding);
   8.101          NDIS_SET_PACKET_STATUS(packets[packet_count], NDIS_STATUS_SUCCESS);
   8.102 -        NDIS_SET_PACKET_TIME_RECEIVED(packets[packet_count], time_received.QuadPart);
   8.103          packet_count++;
   8.104          if (packet_count == NET_RX_RING_SIZE)
   8.105          {
   8.106 +          /* A miniport driver must release any spin lock that it is holding before calling NdisMIndicateReceivePacket */
   8.107            NdisMIndicateReceivePacket(xi->adapter_handle, packets, packet_count);
   8.108            packet_count = 0;
   8.109          }
   8.110 @@ -206,7 +266,7 @@ XenNet_RxBufferCheck(struct xennet_info 
   8.111    /* Give netback more buffers */
   8.112    XenNet_RxBufferAlloc(xi);
   8.113  
   8.114 -  KeReleaseSpinLock(&xi->rx_lock, OldIrql);
   8.115 +  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   8.116  
   8.117  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   8.118  
   8.119 @@ -248,12 +308,6 @@ XenNet_ReturnPacket(
   8.120  
   8.121    NdisFreePacket(Packet);
   8.122    
   8.123 -  InterlockedDecrement(&xi->rx_outstanding);
   8.124 -
   8.125 -  // if we are no longer connected then _halt needs to know when rx_outstanding reaches zero
   8.126 -  if (!xi->connected && !xi->rx_outstanding)
   8.127 -    KeSetEvent(&xi->shutdown_event, 1, FALSE);  
   8.128 -
   8.129  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   8.130  
   8.131  #if defined(XEN_PROFILE)
   8.132 @@ -292,13 +346,15 @@ XenNet_RxInit(xennet_info_t *xi)
   8.133  
   8.134    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   8.135  
   8.136 +  xi->page_free = 0;
   8.137 +  
   8.138    xi->rx_mdl = AllocatePage();
   8.139    xi->rx_pgs = MmGetMdlVirtualAddress(xi->rx_mdl);
   8.140    SHARED_RING_INIT(xi->rx_pgs);
   8.141    FRONT_RING_INIT(&xi->rx, xi->rx_pgs, PAGE_SIZE);
   8.142    xi->rx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
   8.143      xi->XenInterface.InterfaceHeader.Context, 0,
   8.144 -    *MmGetMdlPfnArray(xi->rx_mdl), FALSE);
   8.145 +    *MmGetMdlPfnArray(xi->rx_mdl), FALSE, 0);
   8.146    xi->rx_id_free = 0;
   8.147    for (i = 0; i < NET_RX_RING_SIZE; i++)
   8.148    {
   8.149 @@ -319,6 +375,17 @@ XenNet_RxShutdown(xennet_info_t *xi)
   8.150  
   8.151    XenNet_RxBufferFree(xi);
   8.152  
   8.153 +  free_page_freelist(xi);
   8.154 +
   8.155 +  /* free RX resources */
   8.156 +  if (xi->XenInterface.GntTbl_EndAccess(
   8.157 +    xi->XenInterface.InterfaceHeader.Context, xi->rx_ring_ref, 0))
   8.158 +  {
   8.159 +    xi->rx_ring_ref = GRANT_INVALID_REF;
   8.160 +    FreePages(xi->rx_mdl);
   8.161 +  }
   8.162 +  xi->rx_pgs = NULL;
   8.163 +
   8.164    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   8.165  
   8.166    return TRUE;
     9.1 --- a/xennet/xennet_tx.c	Sun Mar 02 22:13:49 2008 +1100
     9.2 +++ b/xennet/xennet_tx.c	Wed Mar 05 20:44:14 2008 +1100
     9.3 @@ -21,7 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fi
     9.4  #include "xennet.h"
     9.5  
     9.6  static USHORT
     9.7 -get_tx_id_from_freelist(struct xennet_info *xi)
     9.8 +get_id_from_freelist(struct xennet_info *xi)
     9.9  {
    9.10    if (xi->tx_id_free == 0)
    9.11      return 0xFFFF;
    9.12 @@ -30,60 +30,26 @@ get_tx_id_from_freelist(struct xennet_in
    9.13  }
    9.14  
    9.15  static VOID
    9.16 -put_tx_id_on_freelist(struct xennet_info *xi, USHORT id)
    9.17 +put_id_on_freelist(struct xennet_info *xi, USHORT id)
    9.18  {
    9.19    xi->tx_id_list[xi->tx_id_free] = id;
    9.20    xi->tx_id_free++;
    9.21  }
    9.22  
    9.23 -/* Called at DISPATCH_LEVEL with tx_lock held */
    9.24 -static PMDL
    9.25 -XenNet_Linearize(struct xennet_info *xi, PNDIS_PACKET Packet)
    9.26 +static grant_ref_t
    9.27 +get_gref_from_freelist(struct xennet_info *xi)
    9.28  {
    9.29 -  PMDL pmdl;
    9.30 -  char *start;
    9.31 -  PNDIS_BUFFER buffer;
    9.32 -  PVOID buff_va;
    9.33 -  UINT buff_len;
    9.34 -  UINT tot_buff_len;
    9.35 -#if defined(XEN_PROFILE)
    9.36 -  LARGE_INTEGER tsc, dummy;
    9.37 -#endif
    9.38 -
    9.39 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    9.40 -
    9.41 -#if defined(XEN_PROFILE)
    9.42 -  tsc = KeQueryPerformanceCounter(&dummy);
    9.43 -#endif
    9.44 -
    9.45 -  NdisGetFirstBufferFromPacketSafe(Packet, &buffer, &buff_va, &buff_len,
    9.46 -    &tot_buff_len, NormalPagePriority);
    9.47 -  ASSERT(tot_buff_len <= XN_MAX_PKT_SIZE);
    9.48 +  if (xi->tx_gref_free == 0)
    9.49 +    return 0;
    9.50 +  xi->tx_gref_free--;
    9.51 +  return xi->tx_gref_list[xi->tx_gref_free];
    9.52 +}
    9.53  
    9.54 -  pmdl = get_page_from_freelist(xi);
    9.55 -  if (!pmdl)
    9.56 -  {
    9.57 -    KdPrint(("Could not allocate MDL for linearization\n"));
    9.58 -    return NULL;
    9.59 -  }
    9.60 -
    9.61 -  start = MmGetMdlVirtualAddress(pmdl);
    9.62 -
    9.63 -  while (buffer)
    9.64 -  {
    9.65 -    NdisQueryBufferSafe(buffer, &buff_va, &buff_len, NormalPagePriority);
    9.66 -    RtlCopyMemory(start, buff_va, buff_len);
    9.67 -    start += buff_len;
    9.68 -    NdisGetNextBuffer(buffer, &buffer);
    9.69 -  }
    9.70 -
    9.71 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    9.72 -#if defined(XEN_PROFILE)
    9.73 -  ProfTime_Linearize.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
    9.74 -  ProfCount_Linearize++;
    9.75 -#endif
    9.76 -
    9.77 -  return pmdl;
    9.78 +static VOID
    9.79 +put_gref_on_freelist(struct xennet_info *xi, grant_ref_t gref)
    9.80 +{
    9.81 +  xi->tx_gref_list[xi->tx_gref_free] = gref;
    9.82 +  xi->tx_gref_free++;
    9.83  }
    9.84  
    9.85  /* Called at DISPATCH_LEVEL with tx_lock held */
    9.86 @@ -96,12 +62,19 @@ XenNet_SendQueuedPackets(struct xennet_i
    9.87    struct netif_tx_request *tx;
    9.88    unsigned short id;
    9.89    int notify;
    9.90 -  PMDL pmdl;
    9.91 -  UINT pkt_size;
    9.92  #if defined(XEN_PROFILE)
    9.93    LARGE_INTEGER tsc, dummy;
    9.94  #endif
    9.95    PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    9.96 +  ULONG i;
    9.97 +  PSCATTER_GATHER_LIST sg_list;
    9.98 +  UINT total_packet_length;
    9.99 +  USHORT remaining;
   9.100 +  USHORT offset;
   9.101 +  USHORT length;
   9.102 +  ULONGLONG curr_addr;
   9.103 +  ULONG sg_num;
   9.104 +  ULONG pfn;
   9.105  
   9.106  #if defined(XEN_PROFILE)
   9.107    tsc = KeQueryPerformanceCounter(&dummy);
   9.108 @@ -111,57 +84,94 @@ XenNet_SendQueuedPackets(struct xennet_i
   9.109    /* if empty, the above returns head*, not NULL */
   9.110    while (entry != &xi->tx_waiting_pkt_list)
   9.111    {
   9.112 +//KdPrint((__DRIVER_NAME "     Packet ready to send\n"));
   9.113      packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   9.114 -
   9.115 -    NdisQueryPacket(packet, NULL, NULL, NULL, &pkt_size);
   9.116 -
   9.117 -    id = get_tx_id_from_freelist(xi);
   9.118 -    if (id == 0xFFFF)
   9.119 -    {
   9.120 -      /* whups, out of space on the ring. requeue and get out */
   9.121 -      InsertHeadList(&xi->tx_waiting_pkt_list, entry);
   9.122 -      break;
   9.123 -    }
   9.124 -    //KdPrint(("sending pkt, len %d\n", pkt_size));
   9.125 -    ASSERT(xi->tx_pkts[id] == NULL);
   9.126 -    xi->tx_pkts[id] = packet;
   9.127 -
   9.128 -    pmdl = XenNet_Linearize(xi, packet);
   9.129 -    if (!pmdl)
   9.130 -    {
   9.131 -      KdPrint((__DRIVER_NAME "Couldn't linearize packet!\n"));
   9.132 -      NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   9.133 -      break;
   9.134 -    }
   9.135 +    sg_list = NDIS_PER_PACKET_INFO_FROM_PACKET(packet, ScatterGatherListPacketInfo);
   9.136  
   9.137 -    /* NOTE: 
   9.138 -     * We use the UCHAR[3*sizeof(PVOID)] array in each packet's MiniportReservedEx thusly:
   9.139 -     * 0: PMDL to linearized data
   9.140 -     * sizeof(PVOID)+: LIST_ENTRY for placing packet on the waiting pkt list
   9.141 -     */
   9.142 -    *(PMDL *)&packet->MiniportReservedEx = pmdl;
   9.143 -
   9.144 -    tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   9.145 -    tx->id = id;
   9.146 -    tx->gref = get_grant_ref(pmdl);
   9.147 -    tx->offset = (uint16_t)MmGetMdlByteOffset(pmdl);
   9.148 -    tx->size = (UINT16)pkt_size;
   9.149 -    
   9.150 -    tx->flags = 0;
   9.151 +    i = 0;
   9.152 +    sg_num = 0;
   9.153 +    remaining = 0;
   9.154 +    curr_addr = 0;
   9.155 +    id = 0;
   9.156 +    while (sg_num < sg_list->NumberOfElements || remaining > 0)
   9.157 +    {
   9.158 +      if (remaining == 0)
   9.159 +      {
   9.160 +//KdPrint((__DRIVER_NAME "     First Frag in sg...\n"));
   9.161 +        curr_addr = sg_list->Elements[sg_num].Address.QuadPart;
   9.162 +        offset = (USHORT)(sg_list->Elements[sg_num].Address.QuadPart & (PAGE_SIZE - 1));
   9.163 +        remaining = (USHORT)sg_list->Elements[sg_num].Length;
   9.164 +        length = min(remaining, PAGE_SIZE - offset);
   9.165 +        sg_num++;
   9.166 +      }
   9.167 +      else
   9.168 +      {
   9.169 +//KdPrint((__DRIVER_NAME "     Subsequent Frag in sg...\n"));
   9.170 +        offset = 0;
   9.171 +        length = min(remaining, PAGE_SIZE);
   9.172 +      }
   9.173 +      pfn = (ULONG)(curr_addr >> PAGE_SHIFT);
   9.174 +      remaining = remaining - length;
   9.175 +      curr_addr += length;
   9.176 +      if (i++ < *(ULONG *)&packet->MiniportReservedEx)
   9.177 +        continue;
   9.178 +      id = get_id_from_freelist(xi);
   9.179 +      if (id == 0xFFFF)
   9.180 +      {
   9.181 +//KdPrint((__DRIVER_NAME "     But out of space...\n"));
   9.182 +        /* whups, out of space on the ring. requeue and get out */
   9.183 +        InsertHeadList(&xi->tx_waiting_pkt_list, entry);
   9.184 +        break;
   9.185 +      }
   9.186 +      ASSERT(xi->tx_pkts[id] == NULL);
   9.187 +      (*(ULONG *)&packet->MiniportReservedEx)++;
   9.188 +      tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
   9.189 +      tx->gref = get_gref_from_freelist(xi);
   9.190 +      ASSERT(tx->gref != 0);
   9.191 +      ASSERT(xi->tx_grefs[id] == 0);
   9.192 +      xi->tx_grefs[id] = tx->gref;
   9.193 +      xi->XenInterface.GntTbl_GrantAccess(
   9.194 +        xi->XenInterface.InterfaceHeader.Context, 0,
   9.195 +        pfn, FALSE, tx->gref);
   9.196 +      tx->id = id;
   9.197 +      tx->offset = offset;
   9.198 +      tx->flags = 0;
   9.199 +      if (i == 1) // we have already incremented i!!!
   9.200 +      {
   9.201 +//KdPrint((__DRIVER_NAME "     First Frag in packet...\n"));
   9.202 +        NdisQueryPacket(packet, NULL, NULL, NULL, &total_packet_length);
   9.203 +        tx->size = (USHORT)total_packet_length;
   9.204  #if defined(XEN_PROFILE)
   9.205 -    ProfCount_TxPacketsTotal++;
   9.206 +        ProfCount_TxPacketsTotal++;
   9.207  #endif
   9.208 -    csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpIpChecksumPacketInfo);
   9.209 -    if (csum_info->Transmit.NdisPacketTcpChecksum || csum_info->Transmit.NdisPacketUdpChecksum)
   9.210 -    {
   9.211 -      tx->flags |= NETTXF_csum_blank|NETTXF_data_validated;
   9.212 +        csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpIpChecksumPacketInfo);
   9.213 +        if (csum_info->Transmit.NdisPacketTcpChecksum || csum_info->Transmit.NdisPacketUdpChecksum)
   9.214 +        {
   9.215 +          tx->flags |= NETTXF_csum_blank|NETTXF_data_validated;
   9.216  #if defined(XEN_PROFILE)
   9.217 -      ProfCount_TxPacketsOffload++;
   9.218 +          ProfCount_TxPacketsOffload++;
   9.219  #endif
   9.220 +        }
   9.221 +      }
   9.222 +      else
   9.223 +      {
   9.224 +//KdPrint((__DRIVER_NAME "     Subsequent Frag in packet...\n"));
   9.225 +        tx->size = length;
   9.226 +      }
   9.227 +      if (sg_num == sg_list->NumberOfElements && remaining == 0)
   9.228 +      {
   9.229 +//KdPrint((__DRIVER_NAME "     No more frags\n"));
   9.230 +        xi->tx_pkts[id] = packet; /* only set the packet on the last buffer */
   9.231 +      }
   9.232 +      else
   9.233 +      {
   9.234 +//KdPrint((__DRIVER_NAME "     More frags\n"));
   9.235 +        tx->flags |= NETTXF_more_data;
   9.236 +      }
   9.237 +      xi->tx.req_prod_pvt++;
   9.238      }
   9.239 -
   9.240 -    xi->tx.req_prod_pvt++;
   9.241 -
   9.242 +    if (id == 0xFFFF)
   9.243 +      break;
   9.244      entry = RemoveHeadList(&xi->tx_waiting_pkt_list);
   9.245    }
   9.246  
   9.247 @@ -214,10 +224,15 @@ XenNet_TxBufferGC(struct xennet_info *xi
   9.248          continue; // should this happen? what about the page?
   9.249        id  = txrsp->id;
   9.250        packet = xi->tx_pkts[id];
   9.251 -      xi->tx_pkts[id] = NULL;
   9.252 -      put_tx_id_on_freelist(xi, id);
   9.253 -      put_page_on_freelist(xi, *(PMDL *)packet->MiniportReservedEx);
   9.254 -      NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_SUCCESS);
   9.255 +      if (packet)
   9.256 +      {
   9.257 +        xi->tx_pkts[id] = NULL;
   9.258 +        /* TODO: check status and indicate appropriately */
   9.259 +        NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_SUCCESS);
   9.260 +      }
   9.261 +      put_gref_on_freelist(xi, xi->tx_grefs[id]);
   9.262 +      xi->tx_grefs[id] = 0;
   9.263 +      put_id_on_freelist(xi, id);
   9.264  
   9.265        InterlockedDecrement(&xi->tx_outstanding);
   9.266        xi->stat_tx_ok++;
   9.267 @@ -251,7 +266,7 @@ XenNet_SendPackets(
   9.268    )
   9.269  {
   9.270    struct xennet_info *xi = MiniportAdapterContext;
   9.271 -  PNDIS_PACKET curr_packet;
   9.272 +  PNDIS_PACKET packet;
   9.273    UINT i;
   9.274    PLIST_ENTRY entry;
   9.275    KIRQL OldIrql;
   9.276 @@ -270,11 +285,15 @@ XenNet_SendPackets(
   9.277    //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   9.278    for (i = 0; i < NumberOfPackets; i++)
   9.279    {
   9.280 -    curr_packet = PacketArray[i];
   9.281 -    ASSERT(curr_packet);
   9.282 -    entry = (PLIST_ENTRY)&curr_packet->MiniportReservedEx[sizeof(PVOID)];
   9.283 +    packet = PacketArray[i];
   9.284 +    ASSERT(packet);
   9.285 +    *(ULONG *)&packet->MiniportReservedEx = 0;
   9.286 +    entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   9.287      InsertTailList(&xi->tx_waiting_pkt_list, entry);
   9.288      InterlockedIncrement(&xi->tx_outstanding);
   9.289 +#if defined(XEN_PROFILE)
   9.290 +    ProfCount_PacketsPerSendPackets++;
   9.291 +#endif
   9.292    }
   9.293  
   9.294    XenNet_SendQueuedPackets(xi);
   9.295 @@ -296,6 +315,7 @@ XenNet_SendPackets(
   9.296      KdPrint((__DRIVER_NAME "     RxBufferCheck     Count = %10d, Avg Time = %10ld\n", ProfCount_RxBufferCheck, (ProfCount_RxBufferCheck == 0)?0:(ProfTime_RxBufferCheck.QuadPart / ProfCount_RxBufferCheck)));
   9.297      KdPrint((__DRIVER_NAME "     Linearize         Count = %10d, Avg Time = %10ld\n", ProfCount_Linearize, (ProfCount_Linearize == 0)?0:(ProfTime_Linearize.QuadPart / ProfCount_Linearize)));
   9.298      KdPrint((__DRIVER_NAME "     SendPackets       Count = %10d, Avg Time = %10ld\n", ProfCount_SendPackets, (ProfCount_SendPackets == 0)?0:(ProfTime_SendPackets.QuadPart / ProfCount_SendPackets)));
   9.299 +    KdPrint((__DRIVER_NAME "     Packets per SendPackets = %10d\n", (ProfCount_SendPackets == 0)?0:(ProfCount_PacketsPerSendPackets / ProfCount_SendPackets)));
   9.300      KdPrint((__DRIVER_NAME "     SendQueuedPackets Count = %10d, Avg Time = %10ld\n", ProfCount_SendQueuedPackets, (ProfCount_SendQueuedPackets == 0)?0:(ProfTime_SendQueuedPackets.QuadPart / ProfCount_SendQueuedPackets)));
   9.301      KdPrint((__DRIVER_NAME "     TxBufferGC        Count = %10d, Avg Time = %10ld\n", ProfCount_TxBufferGC, (ProfCount_TxBufferGC == 0)?0:(ProfTime_TxBufferGC.QuadPart / ProfCount_TxBufferGC)));
   9.302      KdPrint((__DRIVER_NAME "     RxPackets         Total = %10d, Offload  = %10d\n", ProfCount_RxPacketsTotal, ProfCount_RxPacketsOffload));
   9.303 @@ -310,8 +330,8 @@ XenNet_TxBufferFree(struct xennet_info *
   9.304  {
   9.305    PLIST_ENTRY entry;
   9.306    PNDIS_PACKET packet;
   9.307 -  PMDL mdl;
   9.308    USHORT i;
   9.309 +  grant_ref_t gref;
   9.310  
   9.311    ASSERT(!xi->connected);
   9.312  
   9.313 @@ -328,13 +348,12 @@ XenNet_TxBufferFree(struct xennet_info *
   9.314    for (i = 0; i < NET_TX_RING_SIZE; i++)
   9.315    {
   9.316      packet = xi->tx_pkts[i];
   9.317 -    if (packet == NULL)
   9.318 -      continue;
   9.319 -
   9.320 -    mdl = *(PMDL *)packet->MiniportReservedEx;
   9.321 -    put_page_on_freelist(xi, mdl);
   9.322 -
   9.323 -    NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   9.324 +    if (packet != NULL)
   9.325 +      NdisMSendComplete(xi->adapter_handle, packet, NDIS_STATUS_FAILURE);
   9.326 +    gref = xi->tx_grefs[i];
   9.327 +    if (gref != 0)
   9.328 +      xi->XenInterface.GntTbl_EndAccess(
   9.329 +        xi->XenInterface.InterfaceHeader.Context, gref, TRUE);
   9.330    }
   9.331  }
   9.332  
   9.333 @@ -349,12 +368,19 @@ XenNet_TxInit(xennet_info_t *xi)
   9.334    FRONT_RING_INIT(&xi->tx, xi->tx_pgs, PAGE_SIZE);
   9.335    xi->tx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
   9.336      xi->XenInterface.InterfaceHeader.Context, 0,
   9.337 -    *MmGetMdlPfnArray(xi->tx_mdl), FALSE);
   9.338 +    *MmGetMdlPfnArray(xi->tx_mdl), FALSE, 0);
   9.339    xi->tx_id_free = 0;
   9.340    for (i = 0; i < NET_TX_RING_SIZE; i++)
   9.341    {
   9.342      xi->tx_pkts[i] = NULL;
   9.343 -    put_tx_id_on_freelist(xi, i);
   9.344 +    put_id_on_freelist(xi, i);
   9.345 +  }
   9.346 +  xi->tx_gref_free = 0;
   9.347 +  for (i = 0; i < NET_TX_RING_SIZE; i++)
   9.348 +  {
   9.349 +    xi->tx_grefs[i] = 0;
   9.350 +    put_gref_on_freelist(xi, xi->XenInterface.GntTbl_GetRef(
   9.351 +      xi->XenInterface.InterfaceHeader.Context));
   9.352    }
   9.353    return TRUE;
   9.354  }
   9.355 @@ -362,6 +388,26 @@ XenNet_TxInit(xennet_info_t *xi)
   9.356  BOOLEAN
   9.357  XenNet_TxShutdown(xennet_info_t *xi)
   9.358  {
   9.359 +  ULONG i;
   9.360 +
   9.361    XenNet_TxBufferFree(xi);
   9.362 +
   9.363 +  /* free TX resources */
   9.364 +  if (xi->XenInterface.GntTbl_EndAccess(
   9.365 +    xi->XenInterface.InterfaceHeader.Context, xi->tx_ring_ref, 0))
   9.366 +  {
   9.367 +    xi->tx_ring_ref = GRANT_INVALID_REF;
   9.368 +    FreePages(xi->tx_mdl);
   9.369 +  }
   9.370 +  /* if EndAccess fails then tx/rx ring pages LEAKED -- it's not safe to reuse
   9.371 +     pages Dom0 still has access to */
   9.372 +  xi->tx_pgs = NULL;
   9.373 +
   9.374 +  for (i = 0; i < NET_TX_RING_SIZE; i++)
   9.375 +  {
   9.376 +    xi->XenInterface.GntTbl_PutRef(
   9.377 +      xi->XenInterface.InterfaceHeader.Context, xi->tx_gref_list[i]);
   9.378 +  }
   9.379 +
   9.380    return TRUE;
   9.381  }
    10.1 --- a/xenpci/gnttbl.c	Sun Mar 02 22:13:49 2008 +1100
    10.2 +++ b/xenpci/gnttbl.c	Wed Mar 05 20:44:14 2008 +1100
    10.3 @@ -19,8 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fi
    10.4  
    10.5  #include "xenpci.h"
    10.6  
    10.7 -static void
    10.8 -put_free_entry(WDFDEVICE Device, grant_ref_t ref)
    10.9 +VOID
   10.10 +GntTbl_PutRef(WDFDEVICE Device, grant_ref_t ref)
   10.11  {
   10.12    PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
   10.13    KIRQL OldIrql;
   10.14 @@ -31,8 +31,8 @@ put_free_entry(WDFDEVICE Device, grant_r
   10.15    KeReleaseSpinLock(&xpdd->grant_lock, OldIrql);
   10.16  }
   10.17  
   10.18 -static grant_ref_t
   10.19 -get_free_entry(WDFDEVICE Device)
   10.20 +grant_ref_t
   10.21 +GntTbl_GetRef(WDFDEVICE Device)
   10.22  {
   10.23    PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
   10.24    unsigned int ref;
   10.25 @@ -47,7 +47,7 @@ get_free_entry(WDFDEVICE Device)
   10.26  }
   10.27  
   10.28  static int 
   10.29 -GntTab_Map(WDFDEVICE Device, unsigned int start_idx, unsigned int end_idx)
   10.30 +GntTbl_Map(WDFDEVICE Device, unsigned int start_idx, unsigned int end_idx)
   10.31  {
   10.32    PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
   10.33    struct xen_add_to_physmap xatp;
   10.34 @@ -83,7 +83,7 @@ GntTbl_Init(WDFDEVICE Device)
   10.35    KeInitializeSpinLock(&xpdd->grant_lock);
   10.36  
   10.37    for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
   10.38 -    put_free_entry(Device, i);
   10.39 +    GntTbl_PutRef(Device, i);
   10.40  
   10.41    xpdd->gnttab_table_physical = XenPCI_AllocMMIO(Device,
   10.42      PAGE_SIZE * NR_GRANT_FRAMES);
   10.43 @@ -94,7 +94,7 @@ GntTbl_Init(WDFDEVICE Device)
   10.44      KdPrint((__DRIVER_NAME "     Error Mapping Grant Table Shared Memory\n"));
   10.45      return;
   10.46    }
   10.47 -  GntTab_Map(Device, 0, NR_GRANT_FRAMES - 1);
   10.48 +  GntTbl_Map(Device, 0, NR_GRANT_FRAMES - 1);
   10.49  
   10.50    //KdPrint((__DRIVER_NAME " <-- GntTbl_Init table mapped at %p\n", gnttab_table));
   10.51  }
   10.52 @@ -104,16 +104,17 @@ GntTbl_GrantAccess(
   10.53    WDFDEVICE Device,
   10.54    domid_t domid,
   10.55    uint32_t frame,
   10.56 -  int readonly)
   10.57 +  int readonly,
   10.58 +  grant_ref_t ref)
   10.59  {
   10.60    PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
   10.61 -  grant_ref_t ref;
   10.62  
   10.63    //KdPrint((__DRIVER_NAME " --> GntTbl_GrantAccess\n"));
   10.64  
   10.65    //KdPrint((__DRIVER_NAME "     Granting access to frame %08x\n", frame));
   10.66  
   10.67 -  ref = get_free_entry(Device);
   10.68 +  if (ref == 0)
   10.69 +    ref = GntTbl_GetRef(Device);
   10.70    xpdd->gnttab_table[ref].frame = frame;
   10.71    xpdd->gnttab_table[ref].domid = domid;
   10.72    KeMemoryBarrier();
   10.73 @@ -128,7 +129,8 @@ GntTbl_GrantAccess(
   10.74  BOOLEAN
   10.75  GntTbl_EndAccess(
   10.76    WDFDEVICE Device,
   10.77 -  grant_ref_t ref)
   10.78 +  grant_ref_t ref,
   10.79 +  BOOLEAN keepref)
   10.80  {
   10.81    PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
   10.82    unsigned short flags, nflags;
   10.83 @@ -145,7 +147,8 @@ GntTbl_EndAccess(
   10.84    } while ((nflags = InterlockedCompareExchange16(
   10.85      (volatile SHORT *)&xpdd->gnttab_table[ref].flags, 0, flags)) != flags);
   10.86  
   10.87 -  put_free_entry(Device, ref);
   10.88 +  if (!keepref)
   10.89 +    GntTbl_PutRef(Device, ref);
   10.90    //KdPrint((__DRIVER_NAME " <-- GntTbl_EndAccess\n"));
   10.91    return TRUE;
   10.92  }
    11.1 --- a/xenpci/xenpci.c	Sun Mar 02 22:13:49 2008 +1100
    11.2 +++ b/xenpci/xenpci.c	Wed Mar 05 20:44:14 2008 +1100
    11.3 @@ -739,7 +739,7 @@ XenPCI_ChildListCreateDevice(
    11.4    memcpy(&ChildDeviceData->InterruptTranslated, &InterruptTranslated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
    11.5    
    11.6    ChildDeviceData->XenInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->XenInterface);
    11.7 -  ChildDeviceData->XenInterface.InterfaceHeader.Version = 1;
    11.8 +  ChildDeviceData->XenInterface.InterfaceHeader.Version = 2;
    11.9    ChildDeviceData->XenInterface.InterfaceHeader.Context = WdfPdoGetParent(ChildDevice);
   11.10    ChildDeviceData->XenInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
   11.11    ChildDeviceData->XenInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
   11.12 @@ -755,6 +755,8 @@ XenPCI_ChildListCreateDevice(
   11.13    ChildDeviceData->XenInterface.EvtChn_AllocUnbound = EvtChn_AllocUnbound;
   11.14    ChildDeviceData->XenInterface.EvtChn_BindDpc = EvtChn_BindDpc;
   11.15  
   11.16 +  ChildDeviceData->XenInterface.GntTbl_GetRef = GntTbl_GetRef;
   11.17 +  ChildDeviceData->XenInterface.GntTbl_PutRef = GntTbl_PutRef;
   11.18    ChildDeviceData->XenInterface.GntTbl_GrantAccess = GntTbl_GrantAccess;
   11.19    ChildDeviceData->XenInterface.GntTbl_EndAccess = GntTbl_EndAccess;
   11.20  
    12.1 --- a/xenpci/xenpci.h	Sun Mar 02 22:13:49 2008 +1100
    12.2 +++ b/xenpci/xenpci.h	Wed Mar 05 20:44:14 2008 +1100
    12.3 @@ -222,8 +222,12 @@ EvtChn_GetXenStoreRingAddr(WDFDEVICE Dev
    12.4  VOID
    12.5  GntTbl_Init(WDFDEVICE Device);
    12.6  grant_ref_t
    12.7 -GntTbl_GrantAccess(WDFDEVICE Device, domid_t domid, uint32_t, int readonly);
    12.8 +GntTbl_GrantAccess(WDFDEVICE Device, domid_t domid, uint32_t, int readonly, grant_ref_t ref);
    12.9  BOOLEAN
   12.10 -GntTbl_EndAccess(WDFDEVICE Device, grant_ref_t ref);
   12.11 +GntTbl_EndAccess(WDFDEVICE Device, grant_ref_t ref, BOOLEAN keepref);
   12.12 +VOID
   12.13 +GntTbl_PutRef(WDFDEVICE Device, grant_ref_t ref);
   12.14 +grant_ref_t
   12.15 +GntTbl_GetRef(WDFDEVICE Device);
   12.16  
   12.17  #endif
    13.1 --- a/xenscsi/xenscsi.c	Sun Mar 02 22:13:49 2008 +1100
    13.2 +++ b/xenscsi/xenscsi.c	Wed Mar 05 20:44:14 2008 +1100
    13.3 @@ -252,7 +252,7 @@ XenScsi_BackEndStateHandler(char *Path, 
    13.4      FRONT_RING_INIT(&TargetData->Ring, SharedRing, PAGE_SIZE);
    13.5      ref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
    13.6        DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
    13.7 -      0, PFN, FALSE);
    13.8 +      0, PFN, FALSE, 0);
    13.9      ASSERT((signed short)ref >= 0);
   13.10      TargetData->ring_detect_state = 0;
   13.11      TargetData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(vscsiif_shadow_t) * VSCSIIF_RING_SIZE, XENSCSI_POOL_TAG);
   13.12 @@ -267,7 +267,7 @@ XenScsi_BackEndStateHandler(char *Path, 
   13.13        {
   13.14          TargetData->shadow[i].req.seg[j].gref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
   13.15            DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
   13.16 -          0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[i].Mdl)[j], FALSE);
   13.17 +          0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[i].Mdl)[j], FALSE, 0);
   13.18          ASSERT((signed short)TargetData->shadow[i].req.seg[j].gref >= 0);
   13.19        }
   13.20      }
    14.1 --- a/xenvbd/xenvbd.c	Sun Mar 02 22:13:49 2008 +1100
    14.2 +++ b/xenvbd/xenvbd.c	Wed Mar 05 20:44:14 2008 +1100
    14.3 @@ -111,17 +111,11 @@ XenVbd_Interrupt(PKINTERRUPT Interrupt, 
    14.4  
    14.5    UNREFERENCED_PARAMETER(Interrupt);
    14.6  
    14.7 -if (DumpMode)
    14.8 -{
    14.9 -  KdPrint((__DRIVER_NAME " --> Interrupt\n"));
   14.10 -}
   14.11 +//  KdPrint((__DRIVER_NAME " --> Interrupt\n"));
   14.12  
   14.13    TargetData->PendingInterrupt = TRUE;
   14.14  
   14.15 -if (DumpMode)
   14.16 -{
   14.17 -  KdPrint((__DRIVER_NAME " <-- Interrupt\n"));
   14.18 -}
   14.19 +//  KdPrint((__DRIVER_NAME " <-- Interrupt\n"));
   14.20  
   14.21    return TRUE;
   14.22  }
   14.23 @@ -150,10 +144,7 @@ XenVbd_HwScsiInterruptTarget(PVOID Devic
   14.24    PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
   14.25    int more_to_do = TRUE;
   14.26  
   14.27 -if (DumpMode)
   14.28 -{
   14.29 -  KdPrint((__DRIVER_NAME " --> HwScsiInterruptTarget\n"));
   14.30 -}
   14.31 +//  KdPrint((__DRIVER_NAME " --> HwScsiInterruptTarget\n"));
   14.32  
   14.33    while (more_to_do)
   14.34    {
   14.35 @@ -239,10 +230,7 @@ if (DumpMode)
   14.36      }
   14.37    }
   14.38  
   14.39 -if (DumpMode)
   14.40 -{
   14.41 -  KdPrint((__DRIVER_NAME " <-- HwScsiInterruptTarget\n"));
   14.42 -}
   14.43 +//  KdPrint((__DRIVER_NAME " <-- HwScsiInterruptTarget\n"));
   14.44  }
   14.45  
   14.46  static BOOLEAN
   14.47 @@ -252,10 +240,7 @@ XenVbd_HwScsiInterrupt(PVOID DeviceExten
   14.48    PXENVBD_TARGET_DATA TargetData;
   14.49    int i, j;
   14.50  
   14.51 -if (DumpMode)
   14.52 -{
   14.53 -  KdPrint((__DRIVER_NAME " --> HwScsiInterrupt\n"));
   14.54 -}
   14.55 +//  KdPrint((__DRIVER_NAME " --> HwScsiInterrupt\n"));
   14.56  
   14.57    DeviceData = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData;
   14.58  
   14.59 @@ -270,10 +255,7 @@ if (DumpMode)
   14.60        TargetData->PendingInterrupt = FALSE;
   14.61      }
   14.62    }
   14.63 -if (DumpMode)
   14.64 -{
   14.65 -  KdPrint((__DRIVER_NAME " <-- HwScsiInterrupt\n"));
   14.66 -}
   14.67 +//  KdPrint((__DRIVER_NAME " <-- HwScsiInterrupt\n"));
   14.68  
   14.69    return FALSE;
   14.70  }
   14.71 @@ -331,7 +313,7 @@ XenVbd_BackEndStateHandler(char *Path, P
   14.72      FRONT_RING_INIT(&TargetData->Ring, SharedRing, PAGE_SIZE);
   14.73      ref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
   14.74        DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
   14.75 -      0, PFN, FALSE);
   14.76 +      0, PFN, FALSE, 0);
   14.77      ASSERT((signed short)ref >= 0);
   14.78      TargetData->ring_detect_state = 0;
   14.79      TargetData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE), XENVBD_POOL_TAG);
   14.80 @@ -346,7 +328,7 @@ XenVbd_BackEndStateHandler(char *Path, P
   14.81        {
   14.82          TargetData->shadow[i].req.seg[j].gref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
   14.83            DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
   14.84 -          0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[i].Mdl)[j], FALSE);
   14.85 +          0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[i].Mdl)[j], FALSE, 0);
   14.86          ASSERT((signed short)TargetData->shadow[i].req.seg[j].gref >= 0);
   14.87        }
   14.88      }
   14.89 @@ -820,11 +802,9 @@ XenVbd_CheckBusEnumeratedTimer(PVOID Dev
   14.90  {
   14.91    PXENVBD_DEVICE_DATA DeviceData = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData;
   14.92  
   14.93 -if (DumpMode)
   14.94 -{
   14.95 -  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   14.96 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   14.97 -}
   14.98 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   14.99 +//  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  14.100 +
  14.101    if (DeviceData->EnumeratedDevices >= DeviceData->TotalInitialDevices)
  14.102    {
  14.103      DeviceData->BusChangePending = 0;
  14.104 @@ -835,10 +815,7 @@ if (DumpMode)
  14.105    {
  14.106      ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusEnumeratedTimer, 100000);
  14.107    }
  14.108 -if (DumpMode)
  14.109 -{
  14.110 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  14.111 -}
  14.112 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  14.113  }
  14.114  
  14.115  static VOID 
  14.116 @@ -1001,11 +978,8 @@ XenVbd_HwScsiStartIo(PVOID DeviceExtensi
  14.117    unsigned int i;
  14.118    int notify;
  14.119  
  14.120 -if (DumpMode)
  14.121 -{
  14.122 -  KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
  14.123 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  14.124 -}
  14.125 +//  KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
  14.126 +//  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  14.127  
  14.128    // If we haven't enumerated all the devices yet then just defer the request
  14.129    // A timer will issue a NextRequest to get things started again...
  14.130 @@ -1041,10 +1015,8 @@ if (DumpMode)
  14.131    {
  14.132    case SRB_FUNCTION_EXECUTE_SCSI:
  14.133      cdb = (PCDB)Srb->Cdb;
  14.134 -if (DumpMode)
  14.135 -{
  14.136 -    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_EXECUTE_SCSI\n"));
  14.137 -}
  14.138 +//    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_EXECUTE_SCSI\n"));
  14.139 +
  14.140      switch(cdb->CDB6GENERIC.OperationCode)
  14.141      {
  14.142      case SCSIOP_TEST_UNIT_READY:
  14.143 @@ -1205,10 +1177,7 @@ if (DumpMode)
  14.144        break;
  14.145      case SCSIOP_READ:
  14.146      case SCSIOP_WRITE:
  14.147 -if (DumpMode)
  14.148 -{
  14.149 -      KdPrint((__DRIVER_NAME "     Command = READ/WRITE\n"));
  14.150 -}
  14.151 +//      KdPrint((__DRIVER_NAME "     Command = READ/WRITE\n"));
  14.152        XenVbd_PutSrbOnRing(TargetData, Srb);
  14.153        RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
  14.154        if (notify)
  14.155 @@ -1320,10 +1289,8 @@ if (DumpMode)
  14.156      break;
  14.157    }
  14.158  
  14.159 -if (DumpMode)
  14.160 -{
  14.161 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  14.162 -}
  14.163 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
  14.164 +
  14.165    return TRUE;
  14.166  }
  14.167