]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
Staging: hv: rename RndisFilter.c and .h to rndis_filter.c and .h
authorGreg Kroah-Hartman <gregkh@suse.de>
Thu, 6 May 2010 05:32:08 +0000 (22:32 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 11 May 2010 18:36:17 +0000 (11:36 -0700)
Cc: Hank Janssen <hjanssen@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/hv/Makefile
drivers/staging/hv/RndisFilter.c [deleted file]
drivers/staging/hv/RndisFilter.h [deleted file]
drivers/staging/hv/netvsc.c
drivers/staging/hv/rndis_filter.c [new file with mode: 0644]
drivers/staging/hv/rndis_filter.h [new file with mode: 0644]

index cc75185e3b54f39c19323521766e1cead8b4bfab..685a3200e04e4ce0da50de9575f7ccaffe926f3d 100644 (file)
@@ -9,4 +9,4 @@ hv_vmbus-objs := vmbus_drv.o osd.o \
                 ChannelMgmt.o ChannelInterface.o ring_buffer.o
 hv_storvsc-objs := storvsc_drv.o storvsc.o
 hv_blkvsc-objs := blkvsc_drv.o blkvsc.o
-hv_netvsc-objs := netvsc_drv.o netvsc.o RndisFilter.o
+hv_netvsc-objs := netvsc_drv.o netvsc.o rndis_filter.o
diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
deleted file mode 100644 (file)
index 597c972..0000000
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/if_ether.h>
-
-#include "osd.h"
-#include "logging.h"
-#include "NetVscApi.h"
-#include "RndisFilter.h"
-
-/* Data types */
-struct rndis_filter_driver_object {
-       /* The original driver */
-       struct netvsc_driver InnerDriver;
-};
-
-enum rndis_device_state {
-       RNDIS_DEV_UNINITIALIZED = 0,
-       RNDIS_DEV_INITIALIZING,
-       RNDIS_DEV_INITIALIZED,
-       RNDIS_DEV_DATAINITIALIZED,
-};
-
-struct rndis_device {
-       struct netvsc_device *NetDevice;
-
-       enum rndis_device_state State;
-       u32 LinkStatus;
-       atomic_t NewRequestId;
-
-       spinlock_t request_lock;
-       struct list_head RequestList;
-
-       unsigned char HwMacAddr[ETH_ALEN];
-};
-
-struct rndis_request {
-       struct list_head ListEntry;
-       struct osd_waitevent *WaitEvent;
-
-       /*
-        * FIXME: We assumed a fixed size response here. If we do ever need to
-        * handle a bigger response, we can either define a max response
-        * message or add a response buffer variable above this field
-        */
-       struct rndis_message ResponseMessage;
-
-       /* Simplify allocation by having a netvsc packet inline */
-       struct hv_netvsc_packet Packet;
-       struct hv_page_buffer Buffer;
-       /* FIXME: We assumed a fixed size request here. */
-       struct rndis_message RequestMessage;
-};
-
-
-struct rndis_filter_packet {
-       void *CompletionContext;
-       void (*OnCompletion)(void *context);
-       struct rndis_message Message;
-};
-
-
-static int RndisFilterOnDeviceAdd(struct hv_device *Device,
-                                 void *AdditionalInfo);
-
-static int RndisFilterOnDeviceRemove(struct hv_device *Device);
-
-static void RndisFilterOnCleanup(struct hv_driver *Driver);
-
-static int RndisFilterOnSend(struct hv_device *Device,
-                            struct hv_netvsc_packet *Packet);
-
-static void RndisFilterOnSendCompletion(void *Context);
-
-static void RndisFilterOnSendRequestCompletion(void *Context);
-
-
-/* The one and only */
-static struct rndis_filter_driver_object gRndisFilter;
-
-static struct rndis_device *GetRndisDevice(void)
-{
-       struct rndis_device *device;
-
-       device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
-       if (!device)
-               return NULL;
-
-       spin_lock_init(&device->request_lock);
-
-       INIT_LIST_HEAD(&device->RequestList);
-
-       device->State = RNDIS_DEV_UNINITIALIZED;
-
-       return device;
-}
-
-static struct rndis_request *GetRndisRequest(struct rndis_device *Device,
-                                            u32 MessageType,
-                                            u32 MessageLength)
-{
-       struct rndis_request *request;
-       struct rndis_message *rndisMessage;
-       struct rndis_set_request *set;
-       unsigned long flags;
-
-       request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
-       if (!request)
-               return NULL;
-
-       request->WaitEvent = osd_WaitEventCreate();
-       if (!request->WaitEvent) {
-               kfree(request);
-               return NULL;
-       }
-
-       rndisMessage = &request->RequestMessage;
-       rndisMessage->NdisMessageType = MessageType;
-       rndisMessage->MessageLength = MessageLength;
-
-       /*
-        * Set the request id. This field is always after the rndis header for
-        * request/response packet types so we just used the SetRequest as a
-        * template
-        */
-       set = &rndisMessage->Message.SetRequest;
-       set->RequestId = atomic_inc_return(&Device->NewRequestId);
-
-       /* Add to the request list */
-       spin_lock_irqsave(&Device->request_lock, flags);
-       list_add_tail(&request->ListEntry, &Device->RequestList);
-       spin_unlock_irqrestore(&Device->request_lock, flags);
-
-       return request;
-}
-
-static void PutRndisRequest(struct rndis_device *Device,
-                           struct rndis_request *Request)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&Device->request_lock, flags);
-       list_del(&Request->ListEntry);
-       spin_unlock_irqrestore(&Device->request_lock, flags);
-
-       kfree(Request->WaitEvent);
-       kfree(Request);
-}
-
-static void DumpRndisMessage(struct rndis_message *RndisMessage)
-{
-       switch (RndisMessage->NdisMessageType) {
-       case REMOTE_NDIS_PACKET_MSG:
-               DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
-                          "data offset %u data len %u, # oob %u, "
-                          "oob offset %u, oob len %u, pkt offset %u, "
-                          "pkt len %u",
-                          RndisMessage->MessageLength,
-                          RndisMessage->Message.Packet.DataOffset,
-                          RndisMessage->Message.Packet.DataLength,
-                          RndisMessage->Message.Packet.NumOOBDataElements,
-                          RndisMessage->Message.Packet.OOBDataOffset,
-                          RndisMessage->Message.Packet.OOBDataLength,
-                          RndisMessage->Message.Packet.PerPacketInfoOffset,
-                          RndisMessage->Message.Packet.PerPacketInfoLength);
-               break;
-
-       case REMOTE_NDIS_INITIALIZE_CMPLT:
-               DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
-                       "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
-                       "device flags %d, max xfer size 0x%x, max pkts %u, "
-                       "pkt aligned %u)",
-                       RndisMessage->MessageLength,
-                       RndisMessage->Message.InitializeComplete.RequestId,
-                       RndisMessage->Message.InitializeComplete.Status,
-                       RndisMessage->Message.InitializeComplete.MajorVersion,
-                       RndisMessage->Message.InitializeComplete.MinorVersion,
-                       RndisMessage->Message.InitializeComplete.DeviceFlags,
-                       RndisMessage->Message.InitializeComplete.MaxTransferSize,
-                       RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
-                       RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
-               break;
-
-       case REMOTE_NDIS_QUERY_CMPLT:
-               DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
-                       "(len %u, id 0x%x, status 0x%x, buf len %u, "
-                       "buf offset %u)",
-                       RndisMessage->MessageLength,
-                       RndisMessage->Message.QueryComplete.RequestId,
-                       RndisMessage->Message.QueryComplete.Status,
-                       RndisMessage->Message.QueryComplete.InformationBufferLength,
-                       RndisMessage->Message.QueryComplete.InformationBufferOffset);
-               break;
-
-       case REMOTE_NDIS_SET_CMPLT:
-               DPRINT_DBG(NETVSC,
-                       "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
-                       RndisMessage->MessageLength,
-                       RndisMessage->Message.SetComplete.RequestId,
-                       RndisMessage->Message.SetComplete.Status);
-               break;
-
-       case REMOTE_NDIS_INDICATE_STATUS_MSG:
-               DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
-                       "(len %u, status 0x%x, buf len %u, buf offset %u)",
-                       RndisMessage->MessageLength,
-                       RndisMessage->Message.IndicateStatus.Status,
-                       RndisMessage->Message.IndicateStatus.StatusBufferLength,
-                       RndisMessage->Message.IndicateStatus.StatusBufferOffset);
-               break;
-
-       default:
-               DPRINT_DBG(NETVSC, "0x%x (len %u)",
-                       RndisMessage->NdisMessageType,
-                       RndisMessage->MessageLength);
-               break;
-       }
-}
-
-static int RndisFilterSendRequest(struct rndis_device *Device,
-                                 struct rndis_request *Request)
-{
-       int ret;
-       struct hv_netvsc_packet *packet;
-
-       DPRINT_ENTER(NETVSC);
-
-       /* Setup the packet to send it */
-       packet = &Request->Packet;
-
-       packet->IsDataPacket = false;
-       packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
-       packet->PageBufferCount = 1;
-
-       packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >>
-                                       PAGE_SHIFT;
-       packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
-       packet->PageBuffers[0].Offset =
-               (unsigned long)&Request->RequestMessage & (PAGE_SIZE - 1);
-
-       packet->Completion.Send.SendCompletionContext = Request;/* packet; */
-       packet->Completion.Send.OnSendCompletion =
-               RndisFilterOnSendRequestCompletion;
-       packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
-
-       ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
-       DPRINT_EXIT(NETVSC);
-       return ret;
-}
-
-static void RndisFilterReceiveResponse(struct rndis_device *Device,
-                                      struct rndis_message *Response)
-{
-       struct rndis_request *request = NULL;
-       bool found = false;
-       unsigned long flags;
-
-       DPRINT_ENTER(NETVSC);
-
-       spin_lock_irqsave(&Device->request_lock, flags);
-       list_for_each_entry(request, &Device->RequestList, ListEntry) {
-               /*
-                * All request/response message contains RequestId as the 1st
-                * field
-                */
-               if (request->RequestMessage.Message.InitializeRequest.RequestId
-                   == Response->Message.InitializeComplete.RequestId) {
-                       DPRINT_DBG(NETVSC, "found rndis request for "
-                               "this response (id 0x%x req type 0x%x res "
-                               "type 0x%x)",
-                               request->RequestMessage.Message.InitializeRequest.RequestId,
-                               request->RequestMessage.NdisMessageType,
-                               Response->NdisMessageType);
-
-                       found = true;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&Device->request_lock, flags);
-
-       if (found) {
-               if (Response->MessageLength <= sizeof(struct rndis_message)) {
-                       memcpy(&request->ResponseMessage, Response,
-                              Response->MessageLength);
-               } else {
-                       DPRINT_ERR(NETVSC, "rndis response buffer overflow "
-                                 "detected (size %u max %zu)",
-                                 Response->MessageLength,
-                                 sizeof(struct rndis_filter_packet));
-
-                       if (Response->NdisMessageType ==
-                           REMOTE_NDIS_RESET_CMPLT) {
-                               /* does not have a request id field */
-                               request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
-                       } else {
-                               request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
-                       }
-               }
-
-               osd_WaitEventSet(request->WaitEvent);
-       } else {
-               DPRINT_ERR(NETVSC, "no rndis request found for this response "
-                          "(id 0x%x res type 0x%x)",
-                          Response->Message.InitializeComplete.RequestId,
-                          Response->NdisMessageType);
-       }
-
-       DPRINT_EXIT(NETVSC);
-}
-
-static void RndisFilterReceiveIndicateStatus(struct rndis_device *Device,
-                                            struct rndis_message *Response)
-{
-       struct rndis_indicate_status *indicate =
-                       &Response->Message.IndicateStatus;
-
-       if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT) {
-               gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
-       } else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT) {
-               gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
-       } else {
-               /*
-                * TODO:
-                */
-       }
-}
-
-static void RndisFilterReceiveData(struct rndis_device *Device,
-                                  struct rndis_message *Message,
-                                  struct hv_netvsc_packet *Packet)
-{
-       struct rndis_packet *rndisPacket;
-       u32 dataOffset;
-
-       DPRINT_ENTER(NETVSC);
-
-       /* empty ethernet frame ?? */
-       /* ASSERT(Packet->PageBuffers[0].Length > */
-       /*      RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
-
-       rndisPacket = &Message->Message.Packet;
-
-       /*
-        * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
-        * netvsc packet (ie TotalDataBufferLength != MessageLength)
-        */
-
-       /* Remove the rndis header and pass it back up the stack */
-       dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
-
-       Packet->TotalDataBufferLength -= dataOffset;
-       Packet->PageBuffers[0].Offset += dataOffset;
-       Packet->PageBuffers[0].Length -= dataOffset;
-
-       Packet->IsDataPacket = true;
-
-       gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device,
-                                                  Packet);
-
-       DPRINT_EXIT(NETVSC);
-}
-
-static int RndisFilterOnReceive(struct hv_device *Device,
-                               struct hv_netvsc_packet *Packet)
-{
-       struct netvsc_device *netDevice = Device->Extension;
-       struct rndis_device *rndisDevice;
-       struct rndis_message rndisMessage;
-       struct rndis_message *rndisHeader;
-
-       DPRINT_ENTER(NETVSC);
-
-       if (!netDevice)
-               return -EINVAL;
-
-       /* Make sure the rndis device state is initialized */
-       if (!netDevice->Extension) {
-               DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
-                         "dropping this message!");
-               DPRINT_EXIT(NETVSC);
-               return -1;
-       }
-
-       rndisDevice = (struct rndis_device *)netDevice->Extension;
-       if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED) {
-               DPRINT_ERR(NETVSC, "got rndis message but rndis device "
-                          "uninitialized...dropping this message!");
-               DPRINT_EXIT(NETVSC);
-               return -1;
-       }
-
-       rndisHeader = (struct rndis_message *)kmap_atomic(
-                       pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
-
-       rndisHeader = (void *)((unsigned long)rndisHeader +
-                       Packet->PageBuffers[0].Offset);
-
-       /* Make sure we got a valid rndis message */
-       /*
-        * FIXME: There seems to be a bug in set completion msg where its
-        * MessageLength is 16 bytes but the ByteCount field in the xfer page
-        * range shows 52 bytes
-        * */
-#if 0
-       if (Packet->TotalDataBufferLength != rndisHeader->MessageLength) {
-               kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset,
-                             KM_IRQ0);
-
-               DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
-                          "bytes got %u)...dropping this message!",
-                          rndisHeader->MessageLength,
-                          Packet->TotalDataBufferLength);
-               DPRINT_EXIT(NETVSC);
-               return -1;
-       }
-#endif
-
-       if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) &&
-           (rndisHeader->MessageLength > sizeof(struct rndis_message))) {
-               DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow "
-                          "detected (got %u, max %zu)...marking it an error!",
-                          rndisHeader->MessageLength,
-                          sizeof(struct rndis_message));
-       }
-
-       memcpy(&rndisMessage, rndisHeader,
-               (rndisHeader->MessageLength > sizeof(struct rndis_message)) ?
-                       sizeof(struct rndis_message) :
-                       rndisHeader->MessageLength);
-
-       kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
-
-       DumpRndisMessage(&rndisMessage);
-
-       switch (rndisMessage.NdisMessageType) {
-       case REMOTE_NDIS_PACKET_MSG:
-               /* data msg */
-               RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
-               break;
-
-       case REMOTE_NDIS_INITIALIZE_CMPLT:
-       case REMOTE_NDIS_QUERY_CMPLT:
-       case REMOTE_NDIS_SET_CMPLT:
-       /* case REMOTE_NDIS_RESET_CMPLT: */
-       /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
-               /* completion msgs */
-               RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
-               break;
-
-       case REMOTE_NDIS_INDICATE_STATUS_MSG:
-               /* notification msgs */
-               RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
-               break;
-       default:
-               DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)",
-                          rndisMessage.NdisMessageType,
-                          rndisMessage.MessageLength);
-               break;
-       }
-
-       DPRINT_EXIT(NETVSC);
-       return 0;
-}
-
-static int RndisFilterQueryDevice(struct rndis_device *Device, u32 Oid,
-                                 void *Result, u32 *ResultSize)
-{
-       struct rndis_request *request;
-       u32 inresultSize = *ResultSize;
-       struct rndis_query_request *query;
-       struct rndis_query_complete *queryComplete;
-       int ret = 0;
-
-       DPRINT_ENTER(NETVSC);
-
-       if (!Result)
-               return -EINVAL;
-
-       *ResultSize = 0;
-       request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG,
-                       RNDIS_MESSAGE_SIZE(struct rndis_query_request));
-       if (!request) {
-               ret = -1;
-               goto Cleanup;
-       }
-
-       /* Setup the rndis query */
-       query = &request->RequestMessage.Message.QueryRequest;
-       query->Oid = Oid;
-       query->InformationBufferOffset = sizeof(struct rndis_query_request);
-       query->InformationBufferLength = 0;
-       query->DeviceVcHandle = 0;
-
-       ret = RndisFilterSendRequest(Device, request);
-       if (ret != 0)
-               goto Cleanup;
-
-       osd_WaitEventWait(request->WaitEvent);
-
-       /* Copy the response back */
-       queryComplete = &request->ResponseMessage.Message.QueryComplete;
-
-       if (queryComplete->InformationBufferLength > inresultSize) {
-               ret = -1;
-               goto Cleanup;
-       }
-
-       memcpy(Result,
-              (void *)((unsigned long)queryComplete +
-                        queryComplete->InformationBufferOffset),
-              queryComplete->InformationBufferLength);
-
-       *ResultSize = queryComplete->InformationBufferLength;
-
-Cleanup:
-       if (request)
-               PutRndisRequest(Device, request);
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-static int RndisFilterQueryDeviceMac(struct rndis_device *Device)
-{
-       u32 size = ETH_ALEN;
-
-       return RndisFilterQueryDevice(Device,
-                                     RNDIS_OID_802_3_PERMANENT_ADDRESS,
-                                     Device->HwMacAddr, &size);
-}
-
-static int RndisFilterQueryDeviceLinkStatus(struct rndis_device *Device)
-{
-       u32 size = sizeof(u32);
-
-       return RndisFilterQueryDevice(Device,
-                                     RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
-                                     &Device->LinkStatus, &size);
-}
-
-static int RndisFilterSetPacketFilter(struct rndis_device *Device,
-                                     u32 NewFilter)
-{
-       struct rndis_request *request;
-       struct rndis_set_request *set;
-       struct rndis_set_complete *setComplete;
-       u32 status;
-       int ret;
-
-       DPRINT_ENTER(NETVSC);
-
-       /* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
-       /*      sizeof(struct rndis_message)); */
-
-       request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG,
-                       RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
-                       sizeof(u32));
-       if (!request) {
-               ret = -1;
-               goto Cleanup;
-       }
-
-       /* Setup the rndis set */
-       set = &request->RequestMessage.Message.SetRequest;
-       set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
-       set->InformationBufferLength = sizeof(u32);
-       set->InformationBufferOffset = sizeof(struct rndis_set_request);
-
-       memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
-              &NewFilter, sizeof(u32));
-
-       ret = RndisFilterSendRequest(Device, request);
-       if (ret != 0)
-               goto Cleanup;
-
-       ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
-       if (!ret) {
-               ret = -1;
-               DPRINT_ERR(NETVSC, "timeout before we got a set response...");
-               /*
-                * We cant deallocate the request since we may still receive a
-                * send completion for it.
-                */
-               goto Exit;
-       } else {
-               if (ret > 0)
-                       ret = 0;
-               setComplete = &request->ResponseMessage.Message.SetComplete;
-               status = setComplete->Status;
-       }
-
-Cleanup:
-       if (request)
-               PutRndisRequest(Device, request);
-Exit:
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-int RndisFilterInit(struct netvsc_driver *Driver)
-{
-       DPRINT_ENTER(NETVSC);
-
-       DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd",
-                  sizeof(struct rndis_filter_packet));
-
-       Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
-
-       /* Driver->Context = rndisDriver; */
-
-       memset(&gRndisFilter, 0, sizeof(struct rndis_filter_driver_object));
-
-       /*rndisDriver->Driver = Driver;
-
-       ASSERT(Driver->OnLinkStatusChanged);
-       rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
-
-       /* Save the original dispatch handlers before we override it */
-       gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
-       gRndisFilter.InnerDriver.Base.OnDeviceRemove =
-                                       Driver->Base.OnDeviceRemove;
-       gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
-
-       /* ASSERT(Driver->OnSend); */
-       /* ASSERT(Driver->OnReceiveCallback); */
-       gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
-       gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
-       gRndisFilter.InnerDriver.OnLinkStatusChanged =
-                                       Driver->OnLinkStatusChanged;
-
-       /* Override */
-       Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
-       Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
-       Driver->Base.OnCleanup = RndisFilterOnCleanup;
-       Driver->OnSend = RndisFilterOnSend;
-       /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
-       Driver->OnReceiveCallback = RndisFilterOnReceive;
-
-       DPRINT_EXIT(NETVSC);
-
-       return 0;
-}
-
-static int RndisFilterInitDevice(struct rndis_device *Device)
-{
-       struct rndis_request *request;
-       struct rndis_initialize_request *init;
-       struct rndis_initialize_complete *initComplete;
-       u32 status;
-       int ret;
-
-       DPRINT_ENTER(NETVSC);
-
-       request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG,
-                       RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
-       if (!request) {
-               ret = -1;
-               goto Cleanup;
-       }
-
-       /* Setup the rndis set */
-       init = &request->RequestMessage.Message.InitializeRequest;
-       init->MajorVersion = RNDIS_MAJOR_VERSION;
-       init->MinorVersion = RNDIS_MINOR_VERSION;
-       /* FIXME: Use 1536 - rounded ethernet frame size */
-       init->MaxTransferSize = 2048;
-
-       Device->State = RNDIS_DEV_INITIALIZING;
-
-       ret = RndisFilterSendRequest(Device, request);
-       if (ret != 0) {
-               Device->State = RNDIS_DEV_UNINITIALIZED;
-               goto Cleanup;
-       }
-
-       osd_WaitEventWait(request->WaitEvent);
-
-       initComplete = &request->ResponseMessage.Message.InitializeComplete;
-       status = initComplete->Status;
-       if (status == RNDIS_STATUS_SUCCESS) {
-               Device->State = RNDIS_DEV_INITIALIZED;
-               ret = 0;
-       } else {
-               Device->State = RNDIS_DEV_UNINITIALIZED;
-               ret = -1;
-       }
-
-Cleanup:
-       if (request)
-               PutRndisRequest(Device, request);
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-static void RndisFilterHaltDevice(struct rndis_device *Device)
-{
-       struct rndis_request *request;
-       struct rndis_halt_request *halt;
-
-       DPRINT_ENTER(NETVSC);
-
-       /* Attempt to do a rndis device halt */
-       request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG,
-                               RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
-       if (!request)
-               goto Cleanup;
-
-       /* Setup the rndis set */
-       halt = &request->RequestMessage.Message.HaltRequest;
-       halt->RequestId = atomic_inc_return(&Device->NewRequestId);
-
-       /* Ignore return since this msg is optional. */
-       RndisFilterSendRequest(Device, request);
-
-       Device->State = RNDIS_DEV_UNINITIALIZED;
-
-Cleanup:
-       if (request)
-               PutRndisRequest(Device, request);
-       DPRINT_EXIT(NETVSC);
-       return;
-}
-
-static int RndisFilterOpenDevice(struct rndis_device *Device)
-{
-       int ret;
-
-       DPRINT_ENTER(NETVSC);
-
-       if (Device->State != RNDIS_DEV_INITIALIZED)
-               return 0;
-
-       ret = RndisFilterSetPacketFilter(Device,
-                                        NDIS_PACKET_TYPE_BROADCAST |
-                                        NDIS_PACKET_TYPE_DIRECTED);
-       if (ret == 0)
-               Device->State = RNDIS_DEV_DATAINITIALIZED;
-
-       DPRINT_EXIT(NETVSC);
-       return ret;
-}
-
-static int RndisFilterCloseDevice(struct rndis_device *Device)
-{
-       int ret;
-
-       DPRINT_ENTER(NETVSC);
-
-       if (Device->State != RNDIS_DEV_DATAINITIALIZED)
-               return 0;
-
-       ret = RndisFilterSetPacketFilter(Device, 0);
-       if (ret == 0)
-               Device->State = RNDIS_DEV_INITIALIZED;
-
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-static int RndisFilterOnDeviceAdd(struct hv_device *Device,
-                                 void *AdditionalInfo)
-{
-       int ret;
-       struct netvsc_device *netDevice;
-       struct rndis_device *rndisDevice;
-       struct netvsc_device_info *deviceInfo = AdditionalInfo;
-
-       DPRINT_ENTER(NETVSC);
-
-       rndisDevice = GetRndisDevice();
-       if (!rndisDevice) {
-               DPRINT_EXIT(NETVSC);
-               return -1;
-       }
-
-       DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
-
-       /*
-        * Let the inner driver handle this first to create the netvsc channel
-        * NOTE! Once the channel is created, we may get a receive callback
-        * (RndisFilterOnReceive()) before this call is completed
-        */
-       ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
-       if (ret != 0) {
-               kfree(rndisDevice);
-               DPRINT_EXIT(NETVSC);
-               return ret;
-       }
-
-
-       /* Initialize the rndis device */
-       netDevice = Device->Extension;
-       /* ASSERT(netDevice); */
-       /* ASSERT(netDevice->Device); */
-
-       netDevice->Extension = rndisDevice;
-       rndisDevice->NetDevice = netDevice;
-
-       /* Send the rndis initialization message */
-       ret = RndisFilterInitDevice(rndisDevice);
-       if (ret != 0) {
-               /*
-                * TODO: If rndis init failed, we will need to shut down the
-                * channel
-                */
-       }
-
-       /* Get the mac address */
-       ret = RndisFilterQueryDeviceMac(rndisDevice);
-       if (ret != 0) {
-               /*
-                * TODO: shutdown rndis device and the channel
-                */
-       }
-
-       DPRINT_INFO(NETVSC, "Device 0x%p mac addr %pM",
-                   rndisDevice, rndisDevice->HwMacAddr);
-
-       memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, ETH_ALEN);
-
-       RndisFilterQueryDeviceLinkStatus(rndisDevice);
-
-       deviceInfo->LinkState = rndisDevice->LinkStatus;
-       DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice,
-                   ((deviceInfo->LinkState) ? ("down") : ("up")));
-
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-static int RndisFilterOnDeviceRemove(struct hv_device *Device)
-{
-       struct netvsc_device *netDevice = Device->Extension;
-       struct rndis_device *rndisDevice = netDevice->Extension;
-
-       DPRINT_ENTER(NETVSC);
-
-       /* Halt and release the rndis device */
-       RndisFilterHaltDevice(rndisDevice);
-
-       kfree(rndisDevice);
-       netDevice->Extension = NULL;
-
-       /* Pass control to inner driver to remove the device */
-       gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
-
-       DPRINT_EXIT(NETVSC);
-
-       return 0;
-}
-
-static void RndisFilterOnCleanup(struct hv_driver *Driver)
-{
-       DPRINT_ENTER(NETVSC);
-
-       DPRINT_EXIT(NETVSC);
-}
-
-int RndisFilterOnOpen(struct hv_device *Device)
-{
-       int ret;
-       struct netvsc_device *netDevice = Device->Extension;
-
-       DPRINT_ENTER(NETVSC);
-
-       if (!netDevice)
-               return -EINVAL;
-
-       ret = RndisFilterOpenDevice(netDevice->Extension);
-
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-int RndisFilterOnClose(struct hv_device *Device)
-{
-       int ret;
-       struct netvsc_device *netDevice = Device->Extension;
-
-       DPRINT_ENTER(NETVSC);
-
-       if (!netDevice)
-               return -EINVAL;
-
-       ret = RndisFilterCloseDevice(netDevice->Extension);
-
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-static int RndisFilterOnSend(struct hv_device *Device,
-                            struct hv_netvsc_packet *Packet)
-{
-       int ret;
-       struct rndis_filter_packet *filterPacket;
-       struct rndis_message *rndisMessage;
-       struct rndis_packet *rndisPacket;
-       u32 rndisMessageSize;
-
-       DPRINT_ENTER(NETVSC);
-
-       /* Add the rndis header */
-       filterPacket = (struct rndis_filter_packet *)Packet->Extension;
-       /* ASSERT(filterPacket); */
-
-       memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
-
-       rndisMessage = &filterPacket->Message;
-       rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
-
-       rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
-       rndisMessage->MessageLength = Packet->TotalDataBufferLength +
-                                     rndisMessageSize;
-
-       rndisPacket = &rndisMessage->Message.Packet;
-       rndisPacket->DataOffset = sizeof(struct rndis_packet);
-       rndisPacket->DataLength = Packet->TotalDataBufferLength;
-
-       Packet->IsDataPacket = true;
-       Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
-       Packet->PageBuffers[0].Offset =
-                       (unsigned long)rndisMessage & (PAGE_SIZE-1);
-       Packet->PageBuffers[0].Length = rndisMessageSize;
-
-       /* Save the packet send completion and context */
-       filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
-       filterPacket->CompletionContext =
-                               Packet->Completion.Send.SendCompletionContext;
-
-       /* Use ours */
-       Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
-       Packet->Completion.Send.SendCompletionContext = filterPacket;
-
-       ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
-       if (ret != 0) {
-               /*
-                * Reset the completion to originals to allow retries from
-                * above
-                */
-               Packet->Completion.Send.OnSendCompletion =
-                               filterPacket->OnCompletion;
-               Packet->Completion.Send.SendCompletionContext =
-                               filterPacket->CompletionContext;
-       }
-
-       DPRINT_EXIT(NETVSC);
-
-       return ret;
-}
-
-static void RndisFilterOnSendCompletion(void *Context)
-{
-       struct rndis_filter_packet *filterPacket = Context;
-
-       DPRINT_ENTER(NETVSC);
-
-       /* Pass it back to the original handler */
-       filterPacket->OnCompletion(filterPacket->CompletionContext);
-
-       DPRINT_EXIT(NETVSC);
-}
-
-
-static void RndisFilterOnSendRequestCompletion(void *Context)
-{
-       DPRINT_ENTER(NETVSC);
-
-       /* Noop */
-       DPRINT_EXIT(NETVSC);
-}
diff --git a/drivers/staging/hv/RndisFilter.h b/drivers/staging/hv/RndisFilter.h
deleted file mode 100644 (file)
index 764b9bf..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _RNDISFILTER_H_
-#define _RNDISFILTER_H_
-
-#define __struct_bcount(x)
-
-#include "netvsc.h"
-
-#include "rndis.h"
-
-#define RNDIS_HEADER_SIZE      (sizeof(struct rndis_message) - \
-                                sizeof(union rndis_message_container))
-
-#define NDIS_PACKET_TYPE_DIRECTED      0x00000001
-#define NDIS_PACKET_TYPE_MULTICAST     0x00000002
-#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
-#define NDIS_PACKET_TYPE_BROADCAST     0x00000008
-#define NDIS_PACKET_TYPE_SOURCE_ROUTING        0x00000010
-#define NDIS_PACKET_TYPE_PROMISCUOUS   0x00000020
-#define NDIS_PACKET_TYPE_SMT           0x00000040
-#define NDIS_PACKET_TYPE_ALL_LOCAL     0x00000080
-#define NDIS_PACKET_TYPE_GROUP         0x00000100
-#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL        0x00000200
-#define NDIS_PACKET_TYPE_FUNCTIONAL    0x00000400
-#define NDIS_PACKET_TYPE_MAC_FRAME     0x00000800
-
-
-/* Interface */
-
-extern int RndisFilterInit(struct netvsc_driver *driver);
-
-#endif /* _RNDISFILTER_H_ */
index 1000989cc0a7753b2074996679bd21dfeb539912..ba15059c45b2c46313e1b22a517834f7c460ff44 100644 (file)
@@ -26,7 +26,7 @@
 #include "osd.h"
 #include "logging.h"
 #include "netvsc.h"
-#include "RndisFilter.h"
+#include "rndis_filter.h"
 
 
 /* Globals */
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
new file mode 100644 (file)
index 0000000..e6824e0
--- /dev/null
@@ -0,0 +1,997 @@
+/*
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/if_ether.h>
+
+#include "osd.h"
+#include "logging.h"
+#include "NetVscApi.h"
+#include "rndis_filter.h"
+
+/* Data types */
+struct rndis_filter_driver_object {
+       /* The original driver */
+       struct netvsc_driver InnerDriver;
+};
+
+enum rndis_device_state {
+       RNDIS_DEV_UNINITIALIZED = 0,
+       RNDIS_DEV_INITIALIZING,
+       RNDIS_DEV_INITIALIZED,
+       RNDIS_DEV_DATAINITIALIZED,
+};
+
+struct rndis_device {
+       struct netvsc_device *NetDevice;
+
+       enum rndis_device_state State;
+       u32 LinkStatus;
+       atomic_t NewRequestId;
+
+       spinlock_t request_lock;
+       struct list_head RequestList;
+
+       unsigned char HwMacAddr[ETH_ALEN];
+};
+
+struct rndis_request {
+       struct list_head ListEntry;
+       struct osd_waitevent *WaitEvent;
+
+       /*
+        * FIXME: We assumed a fixed size response here. If we do ever need to
+        * handle a bigger response, we can either define a max response
+        * message or add a response buffer variable above this field
+        */
+       struct rndis_message ResponseMessage;
+
+       /* Simplify allocation by having a netvsc packet inline */
+       struct hv_netvsc_packet Packet;
+       struct hv_page_buffer Buffer;
+       /* FIXME: We assumed a fixed size request here. */
+       struct rndis_message RequestMessage;
+};
+
+
+struct rndis_filter_packet {
+       void *CompletionContext;
+       void (*OnCompletion)(void *context);
+       struct rndis_message Message;
+};
+
+
+static int RndisFilterOnDeviceAdd(struct hv_device *Device,
+                                 void *AdditionalInfo);
+
+static int RndisFilterOnDeviceRemove(struct hv_device *Device);
+
+static void RndisFilterOnCleanup(struct hv_driver *Driver);
+
+static int RndisFilterOnSend(struct hv_device *Device,
+                            struct hv_netvsc_packet *Packet);
+
+static void RndisFilterOnSendCompletion(void *Context);
+
+static void RndisFilterOnSendRequestCompletion(void *Context);
+
+
+/* The one and only */
+static struct rndis_filter_driver_object gRndisFilter;
+
+static struct rndis_device *GetRndisDevice(void)
+{
+       struct rndis_device *device;
+
+       device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
+       if (!device)
+               return NULL;
+
+       spin_lock_init(&device->request_lock);
+
+       INIT_LIST_HEAD(&device->RequestList);
+
+       device->State = RNDIS_DEV_UNINITIALIZED;
+
+       return device;
+}
+
+static struct rndis_request *GetRndisRequest(struct rndis_device *Device,
+                                            u32 MessageType,
+                                            u32 MessageLength)
+{
+       struct rndis_request *request;
+       struct rndis_message *rndisMessage;
+       struct rndis_set_request *set;
+       unsigned long flags;
+
+       request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
+       if (!request)
+               return NULL;
+
+       request->WaitEvent = osd_WaitEventCreate();
+       if (!request->WaitEvent) {
+               kfree(request);
+               return NULL;
+       }
+
+       rndisMessage = &request->RequestMessage;
+       rndisMessage->NdisMessageType = MessageType;
+       rndisMessage->MessageLength = MessageLength;
+
+       /*
+        * Set the request id. This field is always after the rndis header for
+        * request/response packet types so we just used the SetRequest as a
+        * template
+        */
+       set = &rndisMessage->Message.SetRequest;
+       set->RequestId = atomic_inc_return(&Device->NewRequestId);
+
+       /* Add to the request list */
+       spin_lock_irqsave(&Device->request_lock, flags);
+       list_add_tail(&request->ListEntry, &Device->RequestList);
+       spin_unlock_irqrestore(&Device->request_lock, flags);
+
+       return request;
+}
+
+static void PutRndisRequest(struct rndis_device *Device,
+                           struct rndis_request *Request)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&Device->request_lock, flags);
+       list_del(&Request->ListEntry);
+       spin_unlock_irqrestore(&Device->request_lock, flags);
+
+       kfree(Request->WaitEvent);
+       kfree(Request);
+}
+
+static void DumpRndisMessage(struct rndis_message *RndisMessage)
+{
+       switch (RndisMessage->NdisMessageType) {
+       case REMOTE_NDIS_PACKET_MSG:
+               DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
+                          "data offset %u data len %u, # oob %u, "
+                          "oob offset %u, oob len %u, pkt offset %u, "
+                          "pkt len %u",
+                          RndisMessage->MessageLength,
+                          RndisMessage->Message.Packet.DataOffset,
+                          RndisMessage->Message.Packet.DataLength,
+                          RndisMessage->Message.Packet.NumOOBDataElements,
+                          RndisMessage->Message.Packet.OOBDataOffset,
+                          RndisMessage->Message.Packet.OOBDataLength,
+                          RndisMessage->Message.Packet.PerPacketInfoOffset,
+                          RndisMessage->Message.Packet.PerPacketInfoLength);
+               break;
+
+       case REMOTE_NDIS_INITIALIZE_CMPLT:
+               DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
+                       "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
+                       "device flags %d, max xfer size 0x%x, max pkts %u, "
+                       "pkt aligned %u)",
+                       RndisMessage->MessageLength,
+                       RndisMessage->Message.InitializeComplete.RequestId,
+                       RndisMessage->Message.InitializeComplete.Status,
+                       RndisMessage->Message.InitializeComplete.MajorVersion,
+                       RndisMessage->Message.InitializeComplete.MinorVersion,
+                       RndisMessage->Message.InitializeComplete.DeviceFlags,
+                       RndisMessage->Message.InitializeComplete.MaxTransferSize,
+                       RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
+                       RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
+               break;
+
+       case REMOTE_NDIS_QUERY_CMPLT:
+               DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
+                       "(len %u, id 0x%x, status 0x%x, buf len %u, "
+                       "buf offset %u)",
+                       RndisMessage->MessageLength,
+                       RndisMessage->Message.QueryComplete.RequestId,
+                       RndisMessage->Message.QueryComplete.Status,
+                       RndisMessage->Message.QueryComplete.InformationBufferLength,
+                       RndisMessage->Message.QueryComplete.InformationBufferOffset);
+               break;
+
+       case REMOTE_NDIS_SET_CMPLT:
+               DPRINT_DBG(NETVSC,
+                       "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
+                       RndisMessage->MessageLength,
+                       RndisMessage->Message.SetComplete.RequestId,
+                       RndisMessage->Message.SetComplete.Status);
+               break;
+
+       case REMOTE_NDIS_INDICATE_STATUS_MSG:
+               DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
+                       "(len %u, status 0x%x, buf len %u, buf offset %u)",
+                       RndisMessage->MessageLength,
+                       RndisMessage->Message.IndicateStatus.Status,
+                       RndisMessage->Message.IndicateStatus.StatusBufferLength,
+                       RndisMessage->Message.IndicateStatus.StatusBufferOffset);
+               break;
+
+       default:
+               DPRINT_DBG(NETVSC, "0x%x (len %u)",
+                       RndisMessage->NdisMessageType,
+                       RndisMessage->MessageLength);
+               break;
+       }
+}
+
+static int RndisFilterSendRequest(struct rndis_device *Device,
+                                 struct rndis_request *Request)
+{
+       int ret;
+       struct hv_netvsc_packet *packet;
+
+       DPRINT_ENTER(NETVSC);
+
+       /* Setup the packet to send it */
+       packet = &Request->Packet;
+
+       packet->IsDataPacket = false;
+       packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
+       packet->PageBufferCount = 1;
+
+       packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >>
+                                       PAGE_SHIFT;
+       packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
+       packet->PageBuffers[0].Offset =
+               (unsigned long)&Request->RequestMessage & (PAGE_SIZE - 1);
+
+       packet->Completion.Send.SendCompletionContext = Request;/* packet; */
+       packet->Completion.Send.OnSendCompletion =
+               RndisFilterOnSendRequestCompletion;
+       packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
+
+       ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
+       DPRINT_EXIT(NETVSC);
+       return ret;
+}
+
+static void RndisFilterReceiveResponse(struct rndis_device *Device,
+                                      struct rndis_message *Response)
+{
+       struct rndis_request *request = NULL;
+       bool found = false;
+       unsigned long flags;
+
+       DPRINT_ENTER(NETVSC);
+
+       spin_lock_irqsave(&Device->request_lock, flags);
+       list_for_each_entry(request, &Device->RequestList, ListEntry) {
+               /*
+                * All request/response message contains RequestId as the 1st
+                * field
+                */
+               if (request->RequestMessage.Message.InitializeRequest.RequestId
+                   == Response->Message.InitializeComplete.RequestId) {
+                       DPRINT_DBG(NETVSC, "found rndis request for "
+                               "this response (id 0x%x req type 0x%x res "
+                               "type 0x%x)",
+                               request->RequestMessage.Message.InitializeRequest.RequestId,
+                               request->RequestMessage.NdisMessageType,
+                               Response->NdisMessageType);
+
+                       found = true;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&Device->request_lock, flags);
+
+       if (found) {
+               if (Response->MessageLength <= sizeof(struct rndis_message)) {
+                       memcpy(&request->ResponseMessage, Response,
+                              Response->MessageLength);
+               } else {
+                       DPRINT_ERR(NETVSC, "rndis response buffer overflow "
+                                 "detected (size %u max %zu)",
+                                 Response->MessageLength,
+                                 sizeof(struct rndis_filter_packet));
+
+                       if (Response->NdisMessageType ==
+                           REMOTE_NDIS_RESET_CMPLT) {
+                               /* does not have a request id field */
+                               request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
+                       } else {
+                               request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
+                       }
+               }
+
+               osd_WaitEventSet(request->WaitEvent);
+       } else {
+               DPRINT_ERR(NETVSC, "no rndis request found for this response "
+                          "(id 0x%x res type 0x%x)",
+                          Response->Message.InitializeComplete.RequestId,
+                          Response->NdisMessageType);
+       }
+
+       DPRINT_EXIT(NETVSC);
+}
+
+static void RndisFilterReceiveIndicateStatus(struct rndis_device *Device,
+                                            struct rndis_message *Response)
+{
+       struct rndis_indicate_status *indicate =
+                       &Response->Message.IndicateStatus;
+
+       if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT) {
+               gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
+       } else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT) {
+               gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
+       } else {
+               /*
+                * TODO:
+                */
+       }
+}
+
+static void RndisFilterReceiveData(struct rndis_device *Device,
+                                  struct rndis_message *Message,
+                                  struct hv_netvsc_packet *Packet)
+{
+       struct rndis_packet *rndisPacket;
+       u32 dataOffset;
+
+       DPRINT_ENTER(NETVSC);
+
+       /* empty ethernet frame ?? */
+       /* ASSERT(Packet->PageBuffers[0].Length > */
+       /*      RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
+
+       rndisPacket = &Message->Message.Packet;
+
+       /*
+        * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
+        * netvsc packet (ie TotalDataBufferLength != MessageLength)
+        */
+
+       /* Remove the rndis header and pass it back up the stack */
+       dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
+
+       Packet->TotalDataBufferLength -= dataOffset;
+       Packet->PageBuffers[0].Offset += dataOffset;
+       Packet->PageBuffers[0].Length -= dataOffset;
+
+       Packet->IsDataPacket = true;
+
+       gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device,
+                                                  Packet);
+
+       DPRINT_EXIT(NETVSC);
+}
+
+static int RndisFilterOnReceive(struct hv_device *Device,
+                               struct hv_netvsc_packet *Packet)
+{
+       struct netvsc_device *netDevice = Device->Extension;
+       struct rndis_device *rndisDevice;
+       struct rndis_message rndisMessage;
+       struct rndis_message *rndisHeader;
+
+       DPRINT_ENTER(NETVSC);
+
+       if (!netDevice)
+               return -EINVAL;
+
+       /* Make sure the rndis device state is initialized */
+       if (!netDevice->Extension) {
+               DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
+                         "dropping this message!");
+               DPRINT_EXIT(NETVSC);
+               return -1;
+       }
+
+       rndisDevice = (struct rndis_device *)netDevice->Extension;
+       if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED) {
+               DPRINT_ERR(NETVSC, "got rndis message but rndis device "
+                          "uninitialized...dropping this message!");
+               DPRINT_EXIT(NETVSC);
+               return -1;
+       }
+
+       rndisHeader = (struct rndis_message *)kmap_atomic(
+                       pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
+
+       rndisHeader = (void *)((unsigned long)rndisHeader +
+                       Packet->PageBuffers[0].Offset);
+
+       /* Make sure we got a valid rndis message */
+       /*
+        * FIXME: There seems to be a bug in set completion msg where its
+        * MessageLength is 16 bytes but the ByteCount field in the xfer page
+        * range shows 52 bytes
+        * */
+#if 0
+       if (Packet->TotalDataBufferLength != rndisHeader->MessageLength) {
+               kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset,
+                             KM_IRQ0);
+
+               DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
+                          "bytes got %u)...dropping this message!",
+                          rndisHeader->MessageLength,
+                          Packet->TotalDataBufferLength);
+               DPRINT_EXIT(NETVSC);
+               return -1;
+       }
+#endif
+
+       if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) &&
+           (rndisHeader->MessageLength > sizeof(struct rndis_message))) {
+               DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow "
+                          "detected (got %u, max %zu)...marking it an error!",
+                          rndisHeader->MessageLength,
+                          sizeof(struct rndis_message));
+       }
+
+       memcpy(&rndisMessage, rndisHeader,
+               (rndisHeader->MessageLength > sizeof(struct rndis_message)) ?
+                       sizeof(struct rndis_message) :
+                       rndisHeader->MessageLength);
+
+       kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
+
+       DumpRndisMessage(&rndisMessage);
+
+       switch (rndisMessage.NdisMessageType) {
+       case REMOTE_NDIS_PACKET_MSG:
+               /* data msg */
+               RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
+               break;
+
+       case REMOTE_NDIS_INITIALIZE_CMPLT:
+       case REMOTE_NDIS_QUERY_CMPLT:
+       case REMOTE_NDIS_SET_CMPLT:
+       /* case REMOTE_NDIS_RESET_CMPLT: */
+       /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
+               /* completion msgs */
+               RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
+               break;
+
+       case REMOTE_NDIS_INDICATE_STATUS_MSG:
+               /* notification msgs */
+               RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
+               break;
+       default:
+               DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)",
+                          rndisMessage.NdisMessageType,
+                          rndisMessage.MessageLength);
+               break;
+       }
+
+       DPRINT_EXIT(NETVSC);
+       return 0;
+}
+
+static int RndisFilterQueryDevice(struct rndis_device *Device, u32 Oid,
+                                 void *Result, u32 *ResultSize)
+{
+       struct rndis_request *request;
+       u32 inresultSize = *ResultSize;
+       struct rndis_query_request *query;
+       struct rndis_query_complete *queryComplete;
+       int ret = 0;
+
+       DPRINT_ENTER(NETVSC);
+
+       if (!Result)
+               return -EINVAL;
+
+       *ResultSize = 0;
+       request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG,
+                       RNDIS_MESSAGE_SIZE(struct rndis_query_request));
+       if (!request) {
+               ret = -1;
+               goto Cleanup;
+       }
+
+       /* Setup the rndis query */
+       query = &request->RequestMessage.Message.QueryRequest;
+       query->Oid = Oid;
+       query->InformationBufferOffset = sizeof(struct rndis_query_request);
+       query->InformationBufferLength = 0;
+       query->DeviceVcHandle = 0;
+
+       ret = RndisFilterSendRequest(Device, request);
+       if (ret != 0)
+               goto Cleanup;
+
+       osd_WaitEventWait(request->WaitEvent);
+
+       /* Copy the response back */
+       queryComplete = &request->ResponseMessage.Message.QueryComplete;
+
+       if (queryComplete->InformationBufferLength > inresultSize) {
+               ret = -1;
+               goto Cleanup;
+       }
+
+       memcpy(Result,
+              (void *)((unsigned long)queryComplete +
+                        queryComplete->InformationBufferOffset),
+              queryComplete->InformationBufferLength);
+
+       *ResultSize = queryComplete->InformationBufferLength;
+
+Cleanup:
+       if (request)
+               PutRndisRequest(Device, request);
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+static int RndisFilterQueryDeviceMac(struct rndis_device *Device)
+{
+       u32 size = ETH_ALEN;
+
+       return RndisFilterQueryDevice(Device,
+                                     RNDIS_OID_802_3_PERMANENT_ADDRESS,
+                                     Device->HwMacAddr, &size);
+}
+
+static int RndisFilterQueryDeviceLinkStatus(struct rndis_device *Device)
+{
+       u32 size = sizeof(u32);
+
+       return RndisFilterQueryDevice(Device,
+                                     RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
+                                     &Device->LinkStatus, &size);
+}
+
+static int RndisFilterSetPacketFilter(struct rndis_device *Device,
+                                     u32 NewFilter)
+{
+       struct rndis_request *request;
+       struct rndis_set_request *set;
+       struct rndis_set_complete *setComplete;
+       u32 status;
+       int ret;
+
+       DPRINT_ENTER(NETVSC);
+
+       /* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
+       /*      sizeof(struct rndis_message)); */
+
+       request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG,
+                       RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
+                       sizeof(u32));
+       if (!request) {
+               ret = -1;
+               goto Cleanup;
+       }
+
+       /* Setup the rndis set */
+       set = &request->RequestMessage.Message.SetRequest;
+       set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
+       set->InformationBufferLength = sizeof(u32);
+       set->InformationBufferOffset = sizeof(struct rndis_set_request);
+
+       memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
+              &NewFilter, sizeof(u32));
+
+       ret = RndisFilterSendRequest(Device, request);
+       if (ret != 0)
+               goto Cleanup;
+
+       ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
+       if (!ret) {
+               ret = -1;
+               DPRINT_ERR(NETVSC, "timeout before we got a set response...");
+               /*
+                * We cant deallocate the request since we may still receive a
+                * send completion for it.
+                */
+               goto Exit;
+       } else {
+               if (ret > 0)
+                       ret = 0;
+               setComplete = &request->ResponseMessage.Message.SetComplete;
+               status = setComplete->Status;
+       }
+
+Cleanup:
+       if (request)
+               PutRndisRequest(Device, request);
+Exit:
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+int RndisFilterInit(struct netvsc_driver *Driver)
+{
+       DPRINT_ENTER(NETVSC);
+
+       DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd",
+                  sizeof(struct rndis_filter_packet));
+
+       Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
+
+       /* Driver->Context = rndisDriver; */
+
+       memset(&gRndisFilter, 0, sizeof(struct rndis_filter_driver_object));
+
+       /*rndisDriver->Driver = Driver;
+
+       ASSERT(Driver->OnLinkStatusChanged);
+       rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
+
+       /* Save the original dispatch handlers before we override it */
+       gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
+       gRndisFilter.InnerDriver.Base.OnDeviceRemove =
+                                       Driver->Base.OnDeviceRemove;
+       gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
+
+       /* ASSERT(Driver->OnSend); */
+       /* ASSERT(Driver->OnReceiveCallback); */
+       gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
+       gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
+       gRndisFilter.InnerDriver.OnLinkStatusChanged =
+                                       Driver->OnLinkStatusChanged;
+
+       /* Override */
+       Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
+       Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
+       Driver->Base.OnCleanup = RndisFilterOnCleanup;
+       Driver->OnSend = RndisFilterOnSend;
+       /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
+       Driver->OnReceiveCallback = RndisFilterOnReceive;
+
+       DPRINT_EXIT(NETVSC);
+
+       return 0;
+}
+
+static int RndisFilterInitDevice(struct rndis_device *Device)
+{
+       struct rndis_request *request;
+       struct rndis_initialize_request *init;
+       struct rndis_initialize_complete *initComplete;
+       u32 status;
+       int ret;
+
+       DPRINT_ENTER(NETVSC);
+
+       request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG,
+                       RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
+       if (!request) {
+               ret = -1;
+               goto Cleanup;
+       }
+
+       /* Setup the rndis set */
+       init = &request->RequestMessage.Message.InitializeRequest;
+       init->MajorVersion = RNDIS_MAJOR_VERSION;
+       init->MinorVersion = RNDIS_MINOR_VERSION;
+       /* FIXME: Use 1536 - rounded ethernet frame size */
+       init->MaxTransferSize = 2048;
+
+       Device->State = RNDIS_DEV_INITIALIZING;
+
+       ret = RndisFilterSendRequest(Device, request);
+       if (ret != 0) {
+               Device->State = RNDIS_DEV_UNINITIALIZED;
+               goto Cleanup;
+       }
+
+       osd_WaitEventWait(request->WaitEvent);
+
+       initComplete = &request->ResponseMessage.Message.InitializeComplete;
+       status = initComplete->Status;
+       if (status == RNDIS_STATUS_SUCCESS) {
+               Device->State = RNDIS_DEV_INITIALIZED;
+               ret = 0;
+       } else {
+               Device->State = RNDIS_DEV_UNINITIALIZED;
+               ret = -1;
+       }
+
+Cleanup:
+       if (request)
+               PutRndisRequest(Device, request);
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+static void RndisFilterHaltDevice(struct rndis_device *Device)
+{
+       struct rndis_request *request;
+       struct rndis_halt_request *halt;
+
+       DPRINT_ENTER(NETVSC);
+
+       /* Attempt to do a rndis device halt */
+       request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG,
+                               RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
+       if (!request)
+               goto Cleanup;
+
+       /* Setup the rndis set */
+       halt = &request->RequestMessage.Message.HaltRequest;
+       halt->RequestId = atomic_inc_return(&Device->NewRequestId);
+
+       /* Ignore return since this msg is optional. */
+       RndisFilterSendRequest(Device, request);
+
+       Device->State = RNDIS_DEV_UNINITIALIZED;
+
+Cleanup:
+       if (request)
+               PutRndisRequest(Device, request);
+       DPRINT_EXIT(NETVSC);
+       return;
+}
+
+static int RndisFilterOpenDevice(struct rndis_device *Device)
+{
+       int ret;
+
+       DPRINT_ENTER(NETVSC);
+
+       if (Device->State != RNDIS_DEV_INITIALIZED)
+               return 0;
+
+       ret = RndisFilterSetPacketFilter(Device,
+                                        NDIS_PACKET_TYPE_BROADCAST |
+                                        NDIS_PACKET_TYPE_DIRECTED);
+       if (ret == 0)
+               Device->State = RNDIS_DEV_DATAINITIALIZED;
+
+       DPRINT_EXIT(NETVSC);
+       return ret;
+}
+
+static int RndisFilterCloseDevice(struct rndis_device *Device)
+{
+       int ret;
+
+       DPRINT_ENTER(NETVSC);
+
+       if (Device->State != RNDIS_DEV_DATAINITIALIZED)
+               return 0;
+
+       ret = RndisFilterSetPacketFilter(Device, 0);
+       if (ret == 0)
+               Device->State = RNDIS_DEV_INITIALIZED;
+
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+static int RndisFilterOnDeviceAdd(struct hv_device *Device,
+                                 void *AdditionalInfo)
+{
+       int ret;
+       struct netvsc_device *netDevice;
+       struct rndis_device *rndisDevice;
+       struct netvsc_device_info *deviceInfo = AdditionalInfo;
+
+       DPRINT_ENTER(NETVSC);
+
+       rndisDevice = GetRndisDevice();
+       if (!rndisDevice) {
+               DPRINT_EXIT(NETVSC);
+               return -1;
+       }
+
+       DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
+
+       /*
+        * Let the inner driver handle this first to create the netvsc channel
+        * NOTE! Once the channel is created, we may get a receive callback
+        * (RndisFilterOnReceive()) before this call is completed
+        */
+       ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
+       if (ret != 0) {
+               kfree(rndisDevice);
+               DPRINT_EXIT(NETVSC);
+               return ret;
+       }
+
+
+       /* Initialize the rndis device */
+       netDevice = Device->Extension;
+       /* ASSERT(netDevice); */
+       /* ASSERT(netDevice->Device); */
+
+       netDevice->Extension = rndisDevice;
+       rndisDevice->NetDevice = netDevice;
+
+       /* Send the rndis initialization message */
+       ret = RndisFilterInitDevice(rndisDevice);
+       if (ret != 0) {
+               /*
+                * TODO: If rndis init failed, we will need to shut down the
+                * channel
+                */
+       }
+
+       /* Get the mac address */
+       ret = RndisFilterQueryDeviceMac(rndisDevice);
+       if (ret != 0) {
+               /*
+                * TODO: shutdown rndis device and the channel
+                */
+       }
+
+       DPRINT_INFO(NETVSC, "Device 0x%p mac addr %pM",
+                   rndisDevice, rndisDevice->HwMacAddr);
+
+       memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, ETH_ALEN);
+
+       RndisFilterQueryDeviceLinkStatus(rndisDevice);
+
+       deviceInfo->LinkState = rndisDevice->LinkStatus;
+       DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice,
+                   ((deviceInfo->LinkState) ? ("down") : ("up")));
+
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+static int RndisFilterOnDeviceRemove(struct hv_device *Device)
+{
+       struct netvsc_device *netDevice = Device->Extension;
+       struct rndis_device *rndisDevice = netDevice->Extension;
+
+       DPRINT_ENTER(NETVSC);
+
+       /* Halt and release the rndis device */
+       RndisFilterHaltDevice(rndisDevice);
+
+       kfree(rndisDevice);
+       netDevice->Extension = NULL;
+
+       /* Pass control to inner driver to remove the device */
+       gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
+
+       DPRINT_EXIT(NETVSC);
+
+       return 0;
+}
+
+static void RndisFilterOnCleanup(struct hv_driver *Driver)
+{
+       DPRINT_ENTER(NETVSC);
+
+       DPRINT_EXIT(NETVSC);
+}
+
+int RndisFilterOnOpen(struct hv_device *Device)
+{
+       int ret;
+       struct netvsc_device *netDevice = Device->Extension;
+
+       DPRINT_ENTER(NETVSC);
+
+       if (!netDevice)
+               return -EINVAL;
+
+       ret = RndisFilterOpenDevice(netDevice->Extension);
+
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+int RndisFilterOnClose(struct hv_device *Device)
+{
+       int ret;
+       struct netvsc_device *netDevice = Device->Extension;
+
+       DPRINT_ENTER(NETVSC);
+
+       if (!netDevice)
+               return -EINVAL;
+
+       ret = RndisFilterCloseDevice(netDevice->Extension);
+
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+static int RndisFilterOnSend(struct hv_device *Device,
+                            struct hv_netvsc_packet *Packet)
+{
+       int ret;
+       struct rndis_filter_packet *filterPacket;
+       struct rndis_message *rndisMessage;
+       struct rndis_packet *rndisPacket;
+       u32 rndisMessageSize;
+
+       DPRINT_ENTER(NETVSC);
+
+       /* Add the rndis header */
+       filterPacket = (struct rndis_filter_packet *)Packet->Extension;
+       /* ASSERT(filterPacket); */
+
+       memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
+
+       rndisMessage = &filterPacket->Message;
+       rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
+
+       rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
+       rndisMessage->MessageLength = Packet->TotalDataBufferLength +
+                                     rndisMessageSize;
+
+       rndisPacket = &rndisMessage->Message.Packet;
+       rndisPacket->DataOffset = sizeof(struct rndis_packet);
+       rndisPacket->DataLength = Packet->TotalDataBufferLength;
+
+       Packet->IsDataPacket = true;
+       Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
+       Packet->PageBuffers[0].Offset =
+                       (unsigned long)rndisMessage & (PAGE_SIZE-1);
+       Packet->PageBuffers[0].Length = rndisMessageSize;
+
+       /* Save the packet send completion and context */
+       filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
+       filterPacket->CompletionContext =
+                               Packet->Completion.Send.SendCompletionContext;
+
+       /* Use ours */
+       Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
+       Packet->Completion.Send.SendCompletionContext = filterPacket;
+
+       ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
+       if (ret != 0) {
+               /*
+                * Reset the completion to originals to allow retries from
+                * above
+                */
+               Packet->Completion.Send.OnSendCompletion =
+                               filterPacket->OnCompletion;
+               Packet->Completion.Send.SendCompletionContext =
+                               filterPacket->CompletionContext;
+       }
+
+       DPRINT_EXIT(NETVSC);
+
+       return ret;
+}
+
+static void RndisFilterOnSendCompletion(void *Context)
+{
+       struct rndis_filter_packet *filterPacket = Context;
+
+       DPRINT_ENTER(NETVSC);
+
+       /* Pass it back to the original handler */
+       filterPacket->OnCompletion(filterPacket->CompletionContext);
+
+       DPRINT_EXIT(NETVSC);
+}
+
+
+static void RndisFilterOnSendRequestCompletion(void *Context)
+{
+       DPRINT_ENTER(NETVSC);
+
+       /* Noop */
+       DPRINT_EXIT(NETVSC);
+}
diff --git a/drivers/staging/hv/rndis_filter.h b/drivers/staging/hv/rndis_filter.h
new file mode 100644 (file)
index 0000000..764b9bf
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2009, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ *
+ */
+
+
+#ifndef _RNDISFILTER_H_
+#define _RNDISFILTER_H_
+
+#define __struct_bcount(x)
+
+#include "netvsc.h"
+
+#include "rndis.h"
+
+#define RNDIS_HEADER_SIZE      (sizeof(struct rndis_message) - \
+                                sizeof(union rndis_message_container))
+
+#define NDIS_PACKET_TYPE_DIRECTED      0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST     0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST     0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING        0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS   0x00000020
+#define NDIS_PACKET_TYPE_SMT           0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL     0x00000080
+#define NDIS_PACKET_TYPE_GROUP         0x00000100
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL        0x00000200
+#define NDIS_PACKET_TYPE_FUNCTIONAL    0x00000400
+#define NDIS_PACKET_TYPE_MAC_FRAME     0x00000800
+
+
+/* Interface */
+
+extern int RndisFilterInit(struct netvsc_driver *driver);
+
+#endif /* _RNDISFILTER_H_ */