win-pvdrivers

changeset 230:93f3ccb775b6

Automated merge with ssh://win-pvdrivers@xenbits.xensource.com/win-pvdrivers.hg
author Andy Grover <andy.grover@oracle.com>
date Wed Mar 26 18:38:16 2008 -0700 (2008-03-26)
parents a9a5b54bee92 9f155354d6ba
children 86394e366a71
files xennet/xennet_tx.c
line diff
     1.1 --- a/common.inc	Wed Mar 26 18:37:06 2008 -0700
     1.2 +++ b/common.inc	Wed Mar 26 18:38:16 2008 -0700
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.8.5.9
     1.5 +VERSION=0.8.5.91
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7  KMDF_VERSION=1
     1.8  !IF $(_NT_TOOLS_VERSION) > 0x700
     2.1 --- a/xennet/xennet.c	Wed Mar 26 18:37:06 2008 -0700
     2.2 +++ b/xennet/xennet.c	Wed Mar 26 18:38:16 2008 -0700
     2.3 @@ -186,6 +186,7 @@ XenNet_Init(
     2.4    )
     2.5  {
     2.6    NDIS_STATUS status;
     2.7 +  LARGE_INTEGER timeout;
     2.8    UINT i;
     2.9    BOOLEAN medium_found = FALSE;
    2.10    struct xennet_info *xi = NULL;
    2.11 @@ -277,13 +278,17 @@ XenNet_Init(
    2.12    if (!NT_SUCCESS(status))
    2.13    {
    2.14      KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
    2.15 -    xi->config_gso = 1;
    2.16 +    xi->config_gso = 0;
    2.17    }
    2.18    else
    2.19    {
    2.20      KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
    2.21      xi->config_gso = config_param->ParameterData.IntegerData;
    2.22 -    ASSERT(xi->config_gso <= 61440);
    2.23 +    if (xi->config_gso > 61440)
    2.24 +    {
    2.25 +      xi->config_gso = 61440;
    2.26 +      KdPrint(("(clipped to %d)\n", xi->config_gso));
    2.27 +    }
    2.28    }
    2.29  
    2.30    NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
    2.31 @@ -324,7 +329,7 @@ XenNet_Init(
    2.32  
    2.33    InitializeListHead(&xi->tx_waiting_pkt_list);
    2.34  
    2.35 -  NdisAllocatePacketPool(&status, &xi->packet_pool, XN_RX_QUEUE_LEN,
    2.36 +  NdisAllocatePacketPool(&status, &xi->packet_pool, XN_RX_QUEUE_LEN * 8,
    2.37      PROTOCOL_RESERVED_SIZE_IN_PACKET);
    2.38    if (status != NDIS_STATUS_SUCCESS)
    2.39    {
    2.40 @@ -478,9 +483,13 @@ XenNet_Init(
    2.41  
    2.42    // wait here for signal that we are all set up
    2.43    while (xi->backend_state != XenbusStateConnected)
    2.44 -    KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
    2.45 +  {
    2.46 +    timeout.QuadPart = -5 * 1000 * 1000 * 100; // 5 seconds
    2.47 +    if (KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, &timeout) != STATUS_SUCCESS)
    2.48 +      KdPrint((__DRIVER_NAME "     Still Waiting for Connected...\n"));
    2.49 +  }
    2.50  
    2.51 -  KdPrint((__DRIVER_NAME "     Connected\n"));
    2.52 +  KdPrint((__DRIVER_NAME "     Backend Connected\n"));
    2.53  
    2.54    /* get mac address */
    2.55    RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/mac", xi->backend_path);
    2.56 @@ -562,6 +571,7 @@ XenNet_Halt(
    2.57    struct xennet_info *xi = MiniportAdapterContext;
    2.58    CHAR TmpPath[MAX_XENBUS_STR_LEN];
    2.59    PVOID if_cxt = xi->XenInterface.InterfaceHeader.Context;
    2.60 +  LARGE_INTEGER timeout;
    2.61  
    2.62    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.63    KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
    2.64 @@ -574,8 +584,11 @@ XenNet_Halt(
    2.65    // wait for backend to set 'Closing' state
    2.66  
    2.67    while (xi->backend_state != XenbusStateClosing)
    2.68 -    KeWaitForSingleObject(&xi->backend_state_change_event, Executive,
    2.69 -      KernelMode, FALSE, NULL);
    2.70 +  {
    2.71 +    timeout.QuadPart = -5 * 1000 * 1000 * 100; // 5 seconds
    2.72 +    if (KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, &timeout) != STATUS_SUCCESS)
    2.73 +      KdPrint((__DRIVER_NAME "     Still Waiting for Closing...\n"));
    2.74 +  }
    2.75  
    2.76    // set frontend state to 'closed'
    2.77    xi->state = XenbusStateClosed;
    2.78 @@ -584,8 +597,11 @@ XenNet_Halt(
    2.79  
    2.80    // wait for backend to set 'Closed' state
    2.81    while (xi->backend_state != XenbusStateClosed)
    2.82 -    KeWaitForSingleObject(&xi->backend_state_change_event, Executive,
    2.83 -      KernelMode, FALSE, NULL);
    2.84 +  {
    2.85 +    timeout.QuadPart = -5 * 1000 * 1000 * 100; // 5 seconds
    2.86 +    if (KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, &timeout) != STATUS_SUCCESS)
    2.87 +      KdPrint((__DRIVER_NAME "     Still Waiting for Closed...\n"));
    2.88 +  }
    2.89  
    2.90    // set frontend state to 'Initialising'
    2.91    xi->state = XenbusStateInitialising;
    2.92 @@ -594,8 +610,11 @@ XenNet_Halt(
    2.93  
    2.94    // wait for backend to set 'InitWait' state
    2.95    while (xi->backend_state != XenbusStateInitWait)
    2.96 -    KeWaitForSingleObject(&xi->backend_state_change_event, Executive,
    2.97 -      KernelMode, FALSE, NULL);
    2.98 +  {
    2.99 +    timeout.QuadPart = -5 * 1000 * 1000 * 100; // 5 seconds
   2.100 +    if (KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, &timeout) != STATUS_SUCCESS)
   2.101 +      KdPrint((__DRIVER_NAME "     Still Waiting for InitWait...\n"));
   2.102 +  }
   2.103  
   2.104    // Disables the interrupt
   2.105    XenNet_Shutdown(xi);
     3.1 --- a/xennet/xennet.h	Wed Mar 26 18:37:06 2008 -0700
     3.2 +++ b/xennet/xennet.h	Wed Mar 26 18:38:16 2008 -0700
     3.3 @@ -94,11 +94,36 @@ Foundation, Inc., 51 Franklin Street, Fi
     3.4  #define XN_VENDOR_DESC "Xensource"
     3.5  #define MAX_XENBUS_STR_LEN 128
     3.6  
     3.7 -
     3.8  #define RX_MIN_TARGET 8
     3.9  #define RX_DFL_MIN_TARGET 128
    3.10  #define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
    3.11  
    3.12 +#define MAX_BUFFERS_PER_PACKET 32
    3.13 +
    3.14 +
    3.15 +typedef struct {
    3.16 +  PNDIS_BUFFER mdls[MAX_BUFFERS_PER_PACKET];
    3.17 +  ULONG mdl_count;
    3.18 +  USHORT curr_mdl;
    3.19 +  USHORT curr_mdl_offset;
    3.20 +  USHORT mss;
    3.21 +  NDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    3.22 +  BOOLEAN csum_calc_required;
    3.23 +  BOOLEAN split_required;
    3.24 +  UCHAR ip_version;
    3.25 +  PUCHAR header;
    3.26 +  UCHAR ip_proto;
    3.27 +  USHORT total_length;
    3.28 +  USHORT ip4_header_length;
    3.29 +  USHORT ip4_length;
    3.30 +  USHORT tcp_header_length;
    3.31 +  USHORT tcp_length;
    3.32 +  USHORT tcp_remaining;
    3.33 +  ULONG tcp_seq;
    3.34 +  BOOLEAN extra_info;
    3.35 +  BOOLEAN more_frags;
    3.36 +} rx_packet_info_t;
    3.37 +
    3.38  struct xennet_info
    3.39  {
    3.40    /* Base device vars */
    3.41 @@ -154,10 +179,8 @@ struct xennet_info
    3.42    PNDIS_BUFFER rx_buffers[NET_RX_RING_SIZE];
    3.43    PMDL page_list[NET_RX_RING_SIZE];
    3.44    ULONG page_free;
    3.45 -  PNDIS_PACKET rx_current_packet;
    3.46 -  PMDL rx_first_mdl;
    3.47 -  USHORT rx_extra_info;
    3.48 -  USHORT rx_first_buffer_length;
    3.49 +
    3.50 +  rx_packet_info_t rxpi;
    3.51  
    3.52    /* Receive-ring batched refills. */
    3.53    ULONG rx_target;
     4.1 --- a/xennet/xennet_oid.c	Wed Mar 26 18:37:06 2008 -0700
     4.2 +++ b/xennet/xennet_oid.c	Wed Mar 26 18:38:16 2008 -0700
     4.3 @@ -211,8 +211,11 @@ XenNet_QueryInformation(
     4.4  
     4.5        len = sizeof(NDIS_TASK_OFFLOAD_HEADER);
     4.6  
     4.7 -      len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
     4.8 -        + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
     4.9 +      if (xi->config_csum)
    4.10 +      {
    4.11 +        len += FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
    4.12 +          + sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
    4.13 +      }
    4.14  
    4.15        if (xi->config_gso)
    4.16        {
    4.17 @@ -224,6 +227,8 @@ XenNet_QueryInformation(
    4.18        {
    4.19            break;
    4.20        }
    4.21 +      KdPrint(("InformationBuffer = %p\n", InformationBuffer));
    4.22 +      KdPrint(("len = %d\n", len));
    4.23  
    4.24        ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
    4.25        if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION
    4.26 @@ -233,48 +238,84 @@ XenNet_QueryInformation(
    4.27          status = NDIS_STATUS_NOT_SUPPORTED;
    4.28          break;
    4.29        }
    4.30 -      ntoh->OffsetFirstTask = ntoh->Size;
    4.31 -
    4.32 -      /* fill in first nto */
    4.33 -      nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
    4.34 -      nto->Version = NDIS_TASK_OFFLOAD_VERSION;
    4.35 -      nto->Size = sizeof(NDIS_TASK_OFFLOAD);
    4.36 -      nto->Task = TcpIpChecksumNdisTask;
    4.37 -      nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
    4.38 +      KdPrint(("ntoh = %p\n", ntoh));
    4.39 +      KdPrint(("ntoh->Size = %d\n", ntoh->Size));
    4.40 +      ntoh->OffsetFirstTask = 0; 
    4.41 +      nto = NULL;
    4.42  
    4.43 -      /* fill in checksum offload struct */
    4.44 -      nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
    4.45 -      nttic->V4Transmit.IpChecksum = 0;
    4.46 -      nttic->V4Transmit.IpOptionsSupported = 0;
    4.47 -      nttic->V4Transmit.TcpChecksum = 1;
    4.48 -      nttic->V4Transmit.TcpOptionsSupported = 1;
    4.49 -      nttic->V4Transmit.UdpChecksum = 1;
    4.50 -      nttic->V4Receive.IpChecksum = 0;
    4.51 -      nttic->V4Receive.IpOptionsSupported = 0;
    4.52 -      nttic->V4Receive.TcpChecksum = 1;
    4.53 -      nttic->V4Receive.TcpOptionsSupported = 1;
    4.54 -      nttic->V4Receive.UdpChecksum = 1;
    4.55 -      nttic->V6Transmit.IpOptionsSupported = 0;
    4.56 -      nttic->V6Transmit.TcpOptionsSupported = 0;
    4.57 -      nttic->V6Transmit.TcpChecksum = 0;
    4.58 -      nttic->V6Transmit.UdpChecksum = 0;
    4.59 -      nttic->V6Receive.IpOptionsSupported = 0;
    4.60 -      nttic->V6Receive.TcpOptionsSupported = 0;
    4.61 -      nttic->V6Receive.TcpChecksum = 0;
    4.62 -      nttic->V6Receive.UdpChecksum = 0;
    4.63 +      if (xi->config_csum)
    4.64 +      {
    4.65 +        if (ntoh->OffsetFirstTask == 0)
    4.66 +        {
    4.67 +          ntoh->OffsetFirstTask = ntoh->Size;
    4.68 +          KdPrint(("ntoh->OffsetFirstTask = %d\n", ntoh->OffsetFirstTask));
    4.69 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
    4.70 +        }
    4.71 +        else
    4.72 +        {
    4.73 +          nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
    4.74 +            + nto->TaskBufferLength;
    4.75 +          KdPrint(("nto->OffsetNextTask = %d\n", nto->OffsetNextTask));
    4.76 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
    4.77 +        }
    4.78 +        /* fill in first nto */
    4.79 +        nto->Version = NDIS_TASK_OFFLOAD_VERSION;
    4.80 +        nto->Size = sizeof(NDIS_TASK_OFFLOAD);
    4.81 +        nto->Task = TcpIpChecksumNdisTask;
    4.82 +        nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
    4.83  
    4.84 +        KdPrint(("config_csum enabled\n"));
    4.85 +        KdPrint(("nto = %p\n", nto));
    4.86 +        KdPrint(("nto->Size = %d\n", nto->Size));
    4.87 +        KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
    4.88 +
    4.89 +        /* fill in checksum offload struct */
    4.90 +        nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
    4.91 +        nttic->V4Transmit.IpChecksum = 0;
    4.92 +        nttic->V4Transmit.IpOptionsSupported = 0;
    4.93 +        nttic->V4Transmit.TcpChecksum = 1;
    4.94 +        nttic->V4Transmit.TcpOptionsSupported = 1;
    4.95 +        nttic->V4Transmit.UdpChecksum = 1;
    4.96 +        nttic->V4Receive.IpChecksum = 1;
    4.97 +        nttic->V4Receive.IpOptionsSupported = 1;
    4.98 +        nttic->V4Receive.TcpChecksum = 1;
    4.99 +        nttic->V4Receive.TcpOptionsSupported = 1;
   4.100 +        nttic->V4Receive.UdpChecksum = 1;
   4.101 +        nttic->V6Transmit.IpOptionsSupported = 0;
   4.102 +        nttic->V6Transmit.TcpOptionsSupported = 0;
   4.103 +        nttic->V6Transmit.TcpChecksum = 0;
   4.104 +        nttic->V6Transmit.UdpChecksum = 0;
   4.105 +        nttic->V6Receive.IpOptionsSupported = 0;
   4.106 +        nttic->V6Receive.TcpOptionsSupported = 0;
   4.107 +        nttic->V6Receive.TcpChecksum = 0;
   4.108 +        nttic->V6Receive.UdpChecksum = 0;
   4.109 +      }
   4.110        if (xi->config_gso)
   4.111        {
   4.112 -        /* offset from start of current NTO to start of next NTO */
   4.113 -        nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   4.114 -          + nto->TaskBufferLength;
   4.115 +        if (ntoh->OffsetFirstTask == 0)
   4.116 +        {
   4.117 +          ntoh->OffsetFirstTask = ntoh->Size;
   4.118 +          KdPrint(("ntoh->OffsetFirstTask = %d\n", ntoh->OffsetFirstTask));
   4.119 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(ntoh) + ntoh->OffsetFirstTask);
   4.120 +        }
   4.121 +        else
   4.122 +        {
   4.123 +          nto->OffsetNextTask = FIELD_OFFSET(NDIS_TASK_OFFLOAD, TaskBuffer)
   4.124 +            + nto->TaskBufferLength;
   4.125 +          KdPrint(("nto->OffsetNextTask = %d\n", nto->OffsetNextTask));
   4.126 +          nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
   4.127 +        }
   4.128    
   4.129          /* fill in second nto */
   4.130 -        nto = (PNDIS_TASK_OFFLOAD)((PCHAR)(nto) + nto->OffsetNextTask);
   4.131          nto->Version = NDIS_TASK_OFFLOAD_VERSION;
   4.132          nto->Size = sizeof(NDIS_TASK_OFFLOAD);
   4.133          nto->Task = TcpLargeSendNdisTask;
   4.134          nto->TaskBufferLength = sizeof(NDIS_TASK_TCP_LARGE_SEND);
   4.135 +
   4.136 +        KdPrint(("config_gso enabled\n"));
   4.137 +        KdPrint(("nto = %p\n", nto));
   4.138 +        KdPrint(("nto->Size = %d\n", nto->Size));
   4.139 +        KdPrint(("nto->TaskBufferLength = %d\n", nto->TaskBufferLength));
   4.140    
   4.141          /* fill in large send struct */
   4.142          nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
   4.143 @@ -285,7 +326,8 @@ XenNet_QueryInformation(
   4.144          nttls->IpOptions = TRUE;
   4.145        }
   4.146  
   4.147 -      nto->OffsetNextTask = 0; /* last one */
   4.148 +      if (!nto)
   4.149 +        nto->OffsetNextTask = 0; /* last one */
   4.150  
   4.151        used_temp_buffer = FALSE;
   4.152        break;
   4.153 @@ -338,7 +380,7 @@ XenNet_SetInformation(
   4.154    PNDIS_TASK_TCP_LARGE_SEND nttls;
   4.155    int offset;
   4.156  
   4.157 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   4.158 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   4.159  
   4.160    UNREFERENCED_PARAMETER(MiniportAdapterContext);
   4.161    UNREFERENCED_PARAMETER(InformationBufferLength);
   4.162 @@ -471,7 +513,6 @@ XenNet_SetInformation(
   4.163        KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
   4.164        break;
   4.165      case OID_TCP_TASK_OFFLOAD:
   4.166 -      // Just fake this for now... ultimately we need to manually calc rx checksum if offload is disabled by windows
   4.167        status = NDIS_STATUS_SUCCESS;
   4.168        KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
   4.169        // we should disable everything here, then enable what has been set
   4.170 @@ -528,6 +569,6 @@ XenNet_SetInformation(
   4.171        status = NDIS_STATUS_NOT_SUPPORTED;
   4.172        break;
   4.173    }
   4.174 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.175 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.176    return status;
   4.177  }
     5.1 --- a/xennet/xennet_rx.c	Wed Mar 26 18:37:06 2008 -0700
     5.2 +++ b/xennet/xennet_rx.c	Wed Mar 26 18:38:16 2008 -0700
     5.3 @@ -112,7 +112,11 @@ XenNet_RxBufferAlloc(struct xennet_info 
     5.4        break;
     5.5      mdl = get_page_from_freelist(xi);
     5.6      if (mdl == NULL)
     5.7 +    {
     5.8 +      KdPrint((__DRIVER_NAME "     Added %d out of %d buffers to rx ring\n", i, batch_target));
     5.9 +      KdPrint((__DRIVER_NAME "     (rx_outstanding = %d)\n", xi->rx_outstanding));
    5.10        break;
    5.11 +    }
    5.12      xi->rx_id_free--;
    5.13  
    5.14      /* Give to netback */
    5.15 @@ -133,7 +137,6 @@ XenNet_RxBufferAlloc(struct xennet_info 
    5.16        xi->event_channel);
    5.17    }
    5.18  
    5.19 -//KdPrint((__DRIVER_NAME "     Added %d out of %d buffers to rx ring\n", i, batch_target));
    5.20  
    5.21  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    5.22  
    5.23 @@ -145,46 +148,342 @@ XenNet_RxBufferAlloc(struct xennet_info 
    5.24    return NDIS_STATUS_SUCCESS;
    5.25  }
    5.26  
    5.27 +#define __NET_USHORT_BYTE_0(x) ((USHORT)(x & 0xFF))
    5.28 +#define __NET_USHORT_BYTE_1(x) ((USHORT)((PUCHAR)&x)[1] & 0xFF)
    5.29 +
    5.30 +#define GET_NET_USHORT(x) ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
    5.31 +#define SET_NET_USHORT(y, x) *((USHORT *)&(y)) = ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
    5.32 +
    5.33 +#define GET_NET_ULONG(x) ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
    5.34 +#define SET_NET_ULONG(y, x) *((ULONG *)&(y)) = ((GET_NET_USHORT(x) << 16) | GET_NET_USHORT(((PUCHAR)&x)[2]))
    5.35 +
    5.36  static VOID
    5.37 -XenNet_SplitRxPacket(
    5.38 - PNDIS_PACKET *packets,
    5.39 - PULONG packet_count,
    5.40 - ULONG total_packet_length
    5.41 +XenNet_ParseHeader(
    5.42 +  struct xennet_info *xi
    5.43  )
    5.44  {
    5.45 -  ULONG mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packets[*packet_count], TcpLargeSendPacketInfo));
    5.46 -  ULONG header_length = 54; //TODO: actually calculate this from the TCP header
    5.47 -  ULONG tcp_length = total_packet_length - header_length;
    5.48 -  ULONG remaining = tcp_length;
    5.49 +  UINT header_length;
    5.50  
    5.51 -  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    5.52 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    5.53  
    5.54 -  KdPrint((__DRIVER_NAME "     mss = %d\n", mss));
    5.55 +  ASSERT(xi->rxpi.mdls[0]);
    5.56 +  
    5.57 +  NdisQueryBufferSafe(xi->rxpi.mdls[0], &xi->rxpi.header, &header_length, NormalPagePriority);
    5.58 +
    5.59 +  if (header_length < XN_HDR_SIZE + 20 + 20) // minimum size of first buffer is ETH + IP + TCP header
    5.60 +  {
    5.61 +    return;
    5.62 +  }
    5.63 +  
    5.64 +  switch (GET_NET_USHORT(xi->rxpi.header[12])) // L2 protocol field
    5.65 +  {
    5.66 +  case 0x0800:
    5.67 +    xi->rxpi.ip_version = (xi->rxpi.header[XN_HDR_SIZE + 0] & 0xF0) >> 4;
    5.68 +    if (xi->rxpi.ip_version != 4)
    5.69 +    {
    5.70 +      KdPrint((__DRIVER_NAME "     ip_version = %d\n", xi->rxpi.ip_version));
    5.71 +      return;
    5.72 +    }
    5.73 +    xi->rxpi.ip4_header_length = (xi->rxpi.header[XN_HDR_SIZE + 0] & 0x0F) << 2;
    5.74 +    if (header_length < (ULONG)(xi->rxpi.ip4_header_length + 20))
    5.75 +    {
    5.76 +      KdPrint((__DRIVER_NAME "     first packet is only %d long, must be >= %d\n", XN_HDR_SIZE + header_length, (ULONG)(XN_HDR_SIZE + xi->rxpi.ip4_header_length + 20)));
    5.77 +      // we need to do something conclusive here...
    5.78 +      return;
    5.79 +    }
    5.80 +    break;
    5.81 +  default:
    5.82 +//    KdPrint((__DRIVER_NAME "     Not IP\n"));
    5.83 +    return;
    5.84 +  }
    5.85 +  xi->rxpi.ip_proto = xi->rxpi.header[XN_HDR_SIZE + 9];
    5.86 +  switch (xi->rxpi.ip_proto)
    5.87 +  {
    5.88 +  case 6:  // TCP
    5.89 +  case 17: // UDP
    5.90 +    break;
    5.91 +  default:
    5.92 +    return;
    5.93 +  }
    5.94 +  xi->rxpi.ip4_length = GET_NET_USHORT(xi->rxpi.header[XN_HDR_SIZE + 2]);
    5.95 +  xi->rxpi.tcp_header_length = (xi->rxpi.header[XN_HDR_SIZE + xi->rxpi.ip4_header_length + 12] & 0xf0) >> 2;
    5.96 +  xi->rxpi.tcp_length = xi->rxpi.ip4_length - xi->rxpi.ip4_header_length - xi->rxpi.tcp_header_length;
    5.97 +  xi->rxpi.tcp_remaining = xi->rxpi.tcp_length;
    5.98 +  xi->rxpi.tcp_seq = GET_NET_ULONG(xi->rxpi.header[XN_HDR_SIZE + xi->rxpi.ip4_header_length + 4]);
    5.99 +  if (xi->rxpi.mss > 0 && xi->rxpi.tcp_length > xi->rxpi.mss)
   5.100 +    xi->rxpi.split_required = TRUE;
   5.101 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.102 +}
   5.103 +
   5.104 +static VOID
   5.105 +XenNet_SumIpHeader(
   5.106 +  struct xennet_info *xi,  
   5.107 +  PNDIS_PACKET packet
   5.108 +)
   5.109 +{
   5.110 +  PMDL mdl;
   5.111 +  UINT total_length;
   5.112 +  UINT buffer_length;
   5.113 +  PUCHAR buffer;
   5.114 +  ULONG csum = 0;
   5.115 +  USHORT i;
   5.116 +
   5.117 +  NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
   5.118 +  ASSERT(mdl);
   5.119 +
   5.120 +  buffer[XN_HDR_SIZE + 10] = 0;
   5.121 +  buffer[XN_HDR_SIZE + 11] = 0;
   5.122 +  for (i = 0; i < xi->rxpi.ip4_header_length; i += 2)
   5.123 +  {
   5.124 +    csum += GET_NET_USHORT(buffer[XN_HDR_SIZE + i]);
   5.125 +  }
   5.126 +  while (csum & 0xFFFF0000)
   5.127 +    csum = (csum & 0xFFFF) + (csum >> 16);
   5.128 +  csum = ~csum;
   5.129 +  SET_NET_USHORT(buffer[XN_HDR_SIZE + 10], csum);
   5.130 +}
   5.131 +
   5.132  
   5.133  /*
   5.134 -  while (remaining)
   5.135 + Windows appears to insist that the checksum on received packets is correct, and won't
   5.136 + believe us when we lie about it, which happens when the packet is generated on the
   5.137 + same bridge in Dom0. Doh!
   5.138 + This is only for TCP and UDP packets. IP checksums appear to be correct anyways.
   5.139 +*/
   5.140 +static VOID
   5.141 +XenNet_SumTcpPacket(
   5.142 +  struct xennet_info *xi,  
   5.143 +  PNDIS_PACKET packet
   5.144 +)
   5.145 +{
   5.146 +  USHORT i;
   5.147 +  PUCHAR buffer;
   5.148 +  PMDL mdl;
   5.149 +  UINT total_length;
   5.150 +  UINT buffer_length;
   5.151 +  USHORT buffer_offset;
   5.152 +  ULONG csum;
   5.153 +  PUSHORT csum_ptr;
   5.154 +  USHORT remaining;
   5.155 +  USHORT ip4_length;
   5.156 +
   5.157 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.158 +
   5.159 +  #if defined(XEN_PROFILE)
   5.160 +  ProfCount_RxPacketsCsumOffload++;
   5.161 +  #endif
   5.162 +
   5.163 +  NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
   5.164 +  ASSERT(mdl);
   5.165 +
   5.166 +  ip4_length = GET_NET_USHORT(buffer[XN_HDR_SIZE + 2]);
   5.167 +
   5.168 +  if ((USHORT)(ip4_length + XN_HDR_SIZE) != total_length)
   5.169    {
   5.170 -    // take the buffers off of the current packet
   5.171 -    KdPrint((__DRIVER_NAME "     Remaining = %d\n", remaining));
   5.172 +    KdPrint((__DRIVER_NAME "     Size Mismatch %d (ip4_length + XN_HDR_SIZE) != %d (total_length)\n", ip4_length + XN_HDR_SIZE, total_length));
   5.173 +  }
   5.174  
   5.175 -    if (remaining > mss)
   5.176 +  csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + xi->rxpi.ip4_header_length + 16];
   5.177 +  *csum_ptr = 0;
   5.178 +
   5.179 +  csum = 0;
   5.180 +  csum += GET_NET_USHORT(buffer[XN_HDR_SIZE + 12]) + GET_NET_USHORT(buffer[XN_HDR_SIZE + 14]); // seq
   5.181 +  csum += GET_NET_USHORT(buffer[XN_HDR_SIZE + 16]) + GET_NET_USHORT(buffer[XN_HDR_SIZE + 18]); // ack
   5.182 +  csum += ((USHORT)buffer[XN_HDR_SIZE + 9]);
   5.183 +
   5.184 +  remaining = ip4_length - xi->rxpi.ip4_header_length;
   5.185 +
   5.186 +  csum += remaining;
   5.187 +
   5.188 +  for (buffer_offset = i = XN_HDR_SIZE + xi->rxpi.ip4_header_length; i < total_length - 1; i += 2, buffer_offset += 2)
   5.189 +  {
   5.190 +    if (buffer_offset == buffer_length - 1) // deal with a buffer ending on an odd byte boundary
   5.191      {
   5.192 -      // tcp length = mss;
   5.193 -      remaining -= mss;
   5.194 +      csum += (USHORT)buffer[buffer_offset] << 8;
   5.195 +      NdisGetNextBuffer(mdl, &mdl);
   5.196 +      if (mdl == NULL)
   5.197 +      {
   5.198 +        KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   5.199 +        return;
   5.200 +      }
   5.201 +      NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
   5.202 +//      KdPrint((__DRIVER_NAME "     New buffer - unaligned...\n"));
   5.203 +      csum += ((USHORT)buffer[0]);
   5.204 +      buffer_offset = (USHORT)-1;
   5.205      }
   5.206      else
   5.207      {
   5.208 -      // tcp length = remaining
   5.209 -      remaining = 0;
   5.210 +      if (buffer_offset == buffer_length)
   5.211 +      {
   5.212 +//        KdPrint((__DRIVER_NAME "     New buffer - aligned...\n"));
   5.213 +        NdisGetNextBuffer(mdl, &mdl);
   5.214 +        if (mdl == NULL)
   5.215 +        {
   5.216 +          KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   5.217 +          return;
   5.218 +        }
   5.219 +        NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
   5.220 +        buffer_offset = 0;
   5.221 +      }
   5.222 +      csum += GET_NET_USHORT(buffer[buffer_offset]);
   5.223 +//KdPrint((__DRIVER_NAME "     %04X\n", GET_NET_USHORT(buffer[buffer_offset])));
   5.224      }
   5.225 -    // do some creative stuff here... clone the header of the previous packet and update the various fields
   5.226 -    // append the remaining data buffers
   5.227 -    // increment the packet count
   5.228    }
   5.229 -*/  
   5.230 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.231 +  if (i != total_length) // last odd byte
   5.232 +  {
   5.233 +//KdPrint((__DRIVER_NAME "    *%04X\n", (USHORT)buffer[buffer_offset] << 8));
   5.234 +    csum += ((USHORT)buffer[buffer_offset] << 8);
   5.235 +  }
   5.236 +  while (csum & 0xFFFF0000)
   5.237 +    csum = (csum & 0xFFFF) + (csum >> 16);
   5.238 +  *csum_ptr = (USHORT)~GET_NET_USHORT(csum);
   5.239  
   5.240 -  return;
   5.241 +//  KdPrint((__DRIVER_NAME "     csum = %04x\n", *csum_ptr));
   5.242 +
   5.243 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.244 +}
   5.245 +
   5.246 +static PUCHAR
   5.247 +XenNet_GetData(
   5.248 +  struct xennet_info *xi,
   5.249 +  USHORT req_length,
   5.250 +  PUSHORT length
   5.251 +)
   5.252 +{
   5.253 +  PNDIS_BUFFER mdl = xi->rxpi.mdls[xi->rxpi.curr_mdl];
   5.254 +  PUCHAR buffer = (PUCHAR)MmGetMdlVirtualAddress(mdl) + xi->rxpi.curr_mdl_offset;
   5.255 +
   5.256 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.257 +
   5.258 +  *length = (USHORT)min(req_length, MmGetMdlByteCount(mdl) - xi->rxpi.curr_mdl_offset);
   5.259 +
   5.260 +//  KdPrint((__DRIVER_NAME "     req_length = %d, length = %d\n", req_length, *length));
   5.261 +
   5.262 +  xi->rxpi.curr_mdl_offset = xi->rxpi.curr_mdl_offset + *length;
   5.263 +  if (xi->rxpi.curr_mdl_offset == MmGetMdlByteCount(mdl))
   5.264 +  {
   5.265 +    xi->rxpi.curr_mdl++;
   5.266 +    xi->rxpi.curr_mdl_offset = 0;
   5.267 +  }
   5.268 +
   5.269 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.270 +
   5.271 +  return buffer;
   5.272 +}
   5.273 +
   5.274 +static PNDIS_PACKET
   5.275 +XenNet_MakePacket(
   5.276 +  struct xennet_info *xi
   5.277 +)
   5.278 +{
   5.279 +  PNDIS_PACKET packet;
   5.280 +  PUCHAR in_buffer;
   5.281 +  PNDIS_BUFFER out_mdl;
   5.282 +  PUCHAR out_buffer;
   5.283 +  USHORT out_offset;
   5.284 +  USHORT out_remaining;
   5.285 +  USHORT length;
   5.286 +  USHORT new_ip4_length;
   5.287 +  NDIS_STATUS status;
   5.288 +  USHORT i;
   5.289 +
   5.290 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.291 +
   5.292 +  NdisAllocatePacket(&status, &packet, xi->packet_pool);
   5.293 +  ASSERT(status == NDIS_STATUS_SUCCESS);
   5.294 +  xi->rx_outstanding++;
   5.295 +  NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
   5.296 +
   5.297 +  if (!xi->rxpi.split_required)
   5.298 +  {
   5.299 +    for (i = 0; i < xi->rxpi.mdl_count; i++)
   5.300 +      NdisChainBufferAtBack(packet, xi->rxpi.mdls[i]);
   5.301 +    NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
   5.302 +  }
   5.303 +  else
   5.304 +  {
   5.305 +    out_mdl = get_page_from_freelist(xi);
   5.306 +    out_buffer = MmGetMdlVirtualAddress(out_mdl);
   5.307 +    out_offset = XN_HDR_SIZE + xi->rxpi.ip4_header_length + xi->rxpi.tcp_header_length;
   5.308 +    out_remaining = min(xi->rxpi.mss, xi->rxpi.tcp_remaining);
   5.309 +    NdisAdjustBufferLength(out_mdl, out_offset + out_remaining);
   5.310 +    memcpy(out_buffer, xi->rxpi.header, out_offset);
   5.311 +    new_ip4_length = out_remaining + xi->rxpi.ip4_header_length + xi->rxpi.tcp_header_length;
   5.312 +    SET_NET_USHORT(out_buffer[XN_HDR_SIZE + 2], new_ip4_length);
   5.313 +    SET_NET_ULONG(out_buffer[XN_HDR_SIZE + xi->rxpi.ip4_header_length + 4], xi->rxpi.tcp_seq);
   5.314 +    xi->rxpi.tcp_seq += out_remaining;
   5.315 +    xi->rxpi.tcp_remaining = xi->rxpi.tcp_remaining - out_remaining;
   5.316 +    do 
   5.317 +    {
   5.318 +      ASSERT(xi->rxpi.curr_mdl < xi->rxpi.mdl_count);
   5.319 +      in_buffer = XenNet_GetData(xi, out_remaining, &length);
   5.320 +      memcpy(&out_buffer[out_offset], in_buffer, length);
   5.321 +      out_remaining = out_remaining - length;
   5.322 +      out_offset = out_offset + length;
   5.323 +    } while (out_remaining != 0); // && in_buffer != NULL);
   5.324 +    NdisChainBufferAtBack(packet, out_mdl);
   5.325 +    XenNet_SumIpHeader(xi, packet);
   5.326 +    NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
   5.327 +  }
   5.328 +
   5.329 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (%p)\n", packet));
   5.330 +  return packet;
   5.331 +}
   5.332 +
   5.333 +static VOID
   5.334 +XenNet_MakePackets(
   5.335 +  struct xennet_info *xi,
   5.336 +  PNDIS_PACKET *packets,
   5.337 +  PULONG packet_count_p
   5.338 +)
   5.339 +{
   5.340 +  USHORT i;
   5.341 +
   5.342 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "(packets = %p, packet_count = %d)\n", packets, *packet_count_p));
   5.343 +
   5.344 +  XenNet_ParseHeader(xi);
   5.345 +  switch (xi->rxpi.ip_proto)
   5.346 +  {
   5.347 +  case 6:  // TCP
   5.348 +    if (xi->rxpi.split_required)
   5.349 +      break;
   5.350 +    // fallthrough
   5.351 +  case 17:  // UDP
   5.352 +    packets[*packet_count_p] = XenNet_MakePacket(xi);
   5.353 +    if (xi->rxpi.csum_calc_required)
   5.354 +      XenNet_SumTcpPacket(xi, packets[*packet_count_p]);
   5.355 +    (*packet_count_p)++;
   5.356 +//    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (TCP/UDP)\n"));
   5.357 +    return;
   5.358 +  default:
   5.359 +    packets[*packet_count_p] = XenNet_MakePacket(xi);
   5.360 +    (*packet_count_p)++;
   5.361 +//    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (Other)\n"));
   5.362 +    return;
   5.363 +  }
   5.364 +//  KdPrint((__DRIVER_NAME "     splitting packet\n"));
   5.365 +  xi->rxpi.tcp_remaining = xi->rxpi.tcp_length;
   5.366 +  if (MmGetMdlByteCount(xi->rxpi.mdls[0]) > (ULONG)(XN_HDR_SIZE + xi->rxpi.ip4_header_length + xi->rxpi.tcp_header_length))
   5.367 +    xi->rxpi.curr_mdl_offset = XN_HDR_SIZE + xi->rxpi.ip4_header_length + xi->rxpi.tcp_header_length;
   5.368 +  else
   5.369 +    xi->rxpi.curr_mdl = 1;
   5.370 +
   5.371 +  while (xi->rxpi.tcp_remaining)
   5.372 +  {
   5.373 +//    KdPrint((__DRIVER_NAME "     tcp_remaining = %d\n", xi->rxpi.tcp_remaining));
   5.374 +    packets[*packet_count_p] = XenNet_MakePacket(xi);
   5.375 +    XenNet_SumTcpPacket(xi, packets[*packet_count_p]);
   5.376 +    (*packet_count_p)++;
   5.377 +  }
   5.378 +  ASSERT(xi->rxpi.curr_mdl == xi->rxpi.mdl_count);
   5.379 +//  KdPrint((__DRIVER_NAME "     tcp_remaining = %d\n", xi->rxpi.tcp_remaining));
   5.380 +  // TODO: restore psh status to last packet
   5.381 +  for (i = 0; i < xi->rxpi.mdl_count; i++)
   5.382 +  {
   5.383 +    NdisAdjustBufferLength(xi->rxpi.mdls[i], PAGE_SIZE);
   5.384 +    put_page_on_freelist(xi, xi->rxpi.mdls[i]);
   5.385 +  }
   5.386 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (split)\n"));
   5.387  }
   5.388  
   5.389  // Called at DISPATCH_LEVEL
   5.390 @@ -195,16 +494,10 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.391    PNDIS_PACKET packets[NET_RX_RING_SIZE];
   5.392    ULONG packet_count;
   5.393    PMDL mdl;
   5.394 -  PMDL first_mdl = NULL;
   5.395    int moretodo;
   5.396    struct netif_rx_response *rxrsp = NULL;
   5.397    struct netif_extra_info *ei;
   5.398 -  int more_frags = 0;
   5.399 -  NDIS_STATUS status;
   5.400    USHORT id;
   5.401 -  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   5.402 -  USHORT total_packet_length = 0;
   5.403 -  USHORT first_buffer_length = 0;
   5.404    int cycles = 0;
   5.405  #if defined(XEN_PROFILE)
   5.406    LARGE_INTEGER tsc, tsc2, dummy;
   5.407 @@ -221,40 +514,31 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.408    KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
   5.409  
   5.410    packet_count = 0;
   5.411 -  if (xi->rx_current_packet)
   5.412 -  {
   5.413 -    packets[0] = xi->rx_current_packet;
   5.414 -    xi->rx_current_packet = NULL;
   5.415 -    first_mdl = xi->rx_first_mdl;
   5.416 -    more_frags = NETRXF_more_data;
   5.417 -    first_buffer_length = xi->rx_first_buffer_length;
   5.418 -  }
   5.419    do {
   5.420      ASSERT(cycles++ < 256);
   5.421      prod = xi->rx.sring->rsp_prod;
   5.422      KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
   5.423  
   5.424 -    for (cons = xi->rx.rsp_cons; cons != prod; cons++) {
   5.425 +    for (cons = xi->rx.rsp_cons; cons != prod; cons++)
   5.426 +    {
   5.427        ASSERT(cycles++ < 256);
   5.428        id = (USHORT)(cons & (NET_RX_RING_SIZE - 1));
   5.429        mdl = xi->rx_buffers[id];
   5.430        xi->rx_buffers[id] = NULL;
   5.431        xi->rx_id_free++;
   5.432 -      if (xi->rx_extra_info)
   5.433 +      if (xi->rxpi.extra_info)
   5.434        {
   5.435 -//KdPrint((__DRIVER_NAME "     RX extra info detected\n"));
   5.436          put_page_on_freelist(xi, mdl);
   5.437          ei = (struct netif_extra_info *)RING_GET_RESPONSE(&xi->rx, cons);
   5.438 -        xi->rx_extra_info = ei->flags & XEN_NETIF_EXTRA_FLAG_MORE;
   5.439 +        xi->rxpi.extra_info = (BOOLEAN)!!(ei->flags & XEN_NETIF_EXTRA_FLAG_MORE);
   5.440          switch (ei->type)
   5.441          {
   5.442          case XEN_NETIF_EXTRA_TYPE_GSO:
   5.443 -//KdPrint((__DRIVER_NAME "     GSO detected - size = %d\n", ei->u.gso.size));
   5.444            switch (ei->u.gso.type)
   5.445            {
   5.446            case XEN_NETIF_GSO_TYPE_TCPV4:
   5.447 -//KdPrint((__DRIVER_NAME "     GSO_TYPE_TCPV4 detected\n"));
   5.448 -            NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo) = (PVOID)(xen_ulong_t)(ei->u.gso.size);
   5.449 +            xi->rxpi.mss = ei->u.gso.size;
   5.450 +            // TODO - put this assertion somewhere ASSERT(header_len + xi->rxpi.mss <= PAGE_SIZE); // this limits MTU to PAGE_SIZE - XN_HEADER_LEN
   5.451              break;
   5.452            default:
   5.453              KdPrint((__DRIVER_NAME "     Unknown GSO type (%d) detected\n", ei->u.gso.type));
   5.454 @@ -268,84 +552,48 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.455        }
   5.456        else
   5.457        {
   5.458 -//KdPrint((__DRIVER_NAME "     normal packet detected\n"));
   5.459          rxrsp = RING_GET_RESPONSE(&xi->rx, cons);
   5.460          if (rxrsp->status <= 0
   5.461            || rxrsp->offset + rxrsp->status > PAGE_SIZE)
   5.462          {
   5.463            KdPrint((__DRIVER_NAME ": Error: rxrsp offset %d, size %d\n",
   5.464              rxrsp->offset, rxrsp->status));
   5.465 +          put_page_on_freelist(xi, mdl);
   5.466            continue;
   5.467          }
   5.468          ASSERT(rxrsp->id == id);
   5.469 -        if (!more_frags) // handling the packet's 1st buffer
   5.470 +        if (!xi->rxpi.more_frags) // handling the packet's 1st buffer
   5.471          {
   5.472 -          first_buffer_length = total_packet_length = rxrsp->status;
   5.473 -          first_mdl = mdl;
   5.474 -          NdisAllocatePacket(&status, &packets[packet_count], xi->packet_pool);
   5.475 -          ASSERT(status == NDIS_STATUS_SUCCESS);
   5.476 -          NDIS_SET_PACKET_HEADER_SIZE(packets[packet_count], XN_HDR_SIZE);
   5.477 -          NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo) = 0;
   5.478 -          if (rxrsp->flags & (NETRXF_csum_blank|NETRXF_data_validated)) // and we are enabled for offload...
   5.479 +          
   5.480 +          if (rxrsp->flags & (NETRXF_csum_blank|NETRXF_data_validated) && xi->config_csum)
   5.481            {
   5.482 -            csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpIpChecksumPacketInfo);
   5.483 -            csum_info->Receive.NdisPacketTcpChecksumSucceeded = 1;
   5.484 -            csum_info->Receive.NdisPacketUdpChecksumSucceeded = 1;
   5.485 -            csum_info->Receive.NdisPacketIpChecksumSucceeded = 1;
   5.486 -#if defined(XEN_PROFILE)
   5.487 -            ProfCount_RxPacketsCsumOffload++;
   5.488 -#endif
   5.489 +            //KdPrint((__DRIVER_NAME "     RX csum blank = %d, validated = %d\n", !!(rxrsp->flags & NETRXF_csum_blank), !!(rxrsp->flags & NETRXF_data_validated)));
   5.490 +            if (rxrsp->flags & NETRXF_csum_blank)
   5.491 +              xi->rxpi.csum_calc_required = TRUE;
   5.492            }
   5.493          }
   5.494 -        else
   5.495 -        {
   5.496 -          NdisAdjustBufferLength(mdl, rxrsp->status);
   5.497 -          NdisChainBufferAtBack(packets[packet_count], mdl);
   5.498 -          first_buffer_length = first_buffer_length  - (USHORT)rxrsp->status;
   5.499 -        }
   5.500 -        
   5.501 -        xi->rx_extra_info = rxrsp->flags & NETRXF_extra_info;
   5.502 -        more_frags = rxrsp->flags & NETRXF_more_data;
   5.503 +        NdisAdjustBufferLength(mdl, rxrsp->status);
   5.504 +        xi->rxpi.mdls[xi->rxpi.mdl_count++] = mdl;
   5.505 +        xi->rxpi.extra_info = (BOOLEAN)!!(rxrsp->flags & NETRXF_extra_info);
   5.506 +        xi->rxpi.more_frags = (BOOLEAN)!!(rxrsp->flags & NETRXF_more_data);
   5.507 +        xi->rxpi.total_length = xi->rxpi.total_length + rxrsp->status;
   5.508        }
   5.509  
   5.510        /* Packet done, add it to the list */
   5.511 -      if (!more_frags && !xi->rx_extra_info)
   5.512 +      if (!xi->rxpi.more_frags && !xi->rxpi.extra_info)
   5.513        {
   5.514 -        NdisAdjustBufferLength(first_mdl, first_buffer_length);
   5.515 -        NdisChainBufferAtFront(packets[packet_count], first_mdl);
   5.516 -
   5.517 -//if (PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo)))
   5.518 -//  KdPrint((__DRIVER_NAME "     first_buffer_length = %d, total length = %d\n", first_buffer_length, total_packet_length));
   5.519 -#if defined(XEN_PROFILE)
   5.520 -        ProfCount_RxPacketsTotal++;
   5.521 -#endif
   5.522 -        xi->stat_rx_ok++;
   5.523 -        NDIS_SET_PACKET_STATUS(packets[packet_count], NDIS_STATUS_SUCCESS);
   5.524 -
   5.525 -        if (total_packet_length > xi->config_mtu + XN_HDR_SIZE)
   5.526 -        {
   5.527 -          KdPrint((__DRIVER_NAME "     total_packet_length %d, config_mtu = %d\n", total_packet_length, xi->config_mtu));
   5.528 -          XenNet_SplitRxPacket(packets, &packet_count, total_packet_length);
   5.529 -        }
   5.530 -
   5.531 -        packet_count++;
   5.532 +        XenNet_MakePackets(xi, packets, &packet_count);
   5.533 +        RtlZeroMemory(&xi->rxpi, sizeof(xi->rxpi));
   5.534        }
   5.535      }
   5.536 +    ASSERT(packet_count < NET_RX_RING_SIZE);
   5.537      xi->rx.rsp_cons = prod;
   5.538 -
   5.539      RING_FINAL_CHECK_FOR_RESPONSES(&xi->rx, moretodo);
   5.540    } while (moretodo);
   5.541  
   5.542    /* Give netback more buffers */
   5.543    XenNet_RxBufferAlloc(xi);
   5.544  
   5.545 -  if (more_frags)
   5.546 -  {
   5.547 -    xi->rx_current_packet = packets[packet_count];
   5.548 -    xi->rx_first_mdl = first_mdl;
   5.549 -    xi->rx_first_buffer_length = first_buffer_length;
   5.550 -  }
   5.551 -
   5.552    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   5.553  
   5.554  #if defined(XEN_PROFILE)
   5.555 @@ -361,7 +609,7 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.556  #endif
   5.557    }
   5.558  
   5.559 -//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.560 +//  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (rx_outstanding = %d)\n", xi->rx_outstanding));
   5.561  
   5.562  #if defined(XEN_PROFILE)
   5.563    ProfTime_RxBufferCheck.QuadPart += KeQueryPerformanceCounter(&dummy).QuadPart - tsc.QuadPart;
   5.564 @@ -387,7 +635,7 @@ XenNet_ReturnPacket(
   5.565    LARGE_INTEGER tsc, dummy;
   5.566  #endif
   5.567  
   5.568 -//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.569 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%p)\n", Packet));
   5.570  
   5.571  #if defined(XEN_PROFILE)
   5.572    tsc = KeQueryPerformanceCounter(&dummy);
   5.573 @@ -404,6 +652,7 @@ XenNet_ReturnPacket(
   5.574      NdisUnchainBufferAtBack(Packet, &mdl);
   5.575    }
   5.576  
   5.577 +  xi->rx_outstanding--;
   5.578    NdisFreePacket(Packet);
   5.579  
   5.580    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   5.581 @@ -446,10 +695,6 @@ XenNet_RxInit(xennet_info_t *xi)
   5.582  
   5.583    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   5.584  
   5.585 -  xi->page_free = 0;
   5.586 -  xi->rx_current_packet = NULL;
   5.587 -  xi->rx_extra_info = 0;
   5.588 -  
   5.589    xi->rx_mdl = AllocatePage();
   5.590    xi->rx_pgs = MmGetMdlVirtualAddress(xi->rx_mdl);
   5.591    SHARED_RING_INIT(xi->rx_pgs);
   5.592 @@ -464,6 +709,7 @@ XenNet_RxInit(xennet_info_t *xi)
   5.593      xi->rx_buffers[i] = NULL;
   5.594    }
   5.595  
   5.596 +  xi->rx_outstanding = 0;
   5.597    XenNet_RxBufferAlloc(xi);
   5.598  
   5.599    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));