1 From fec8755b6193c93a935423fdd6026b354aa2e15e Mon Sep 17 00:00:00 2001
2 From: Hank Janssen <hjanssen@microsoft.com>
3 Date: Mon, 13 Jul 2009 15:34:54 -0700
4 Subject: Staging: hv: add the Hyper-V virtual network driver
6 From: Hank Janssen <hjanssen@microsoft.com>
8 This is the virtual network driver when running Linux on top of Hyper-V.
10 Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
11 Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
12 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
14 drivers/staging/hv/NetVsc.c | 1499 +++++++++++++++++++++++++++++++++++++++
15 drivers/staging/hv/NetVsc.h | 91 ++
16 drivers/staging/hv/RndisFilter.c | 1162 ++++++++++++++++++++++++++++++
17 drivers/staging/hv/RndisFilter.h | 61 +
18 drivers/staging/hv/netvsc_drv.c | 720 ++++++++++++++++++
19 5 files changed, 3533 insertions(+)
20 create mode 100644 drivers/staging/hv/netvsc.c
23 +++ b/drivers/staging/hv/NetVsc.c
27 + * Copyright (c) 2009, Microsoft Corporation.
29 + * This program is free software; you can redistribute it and/or modify it
30 + * under the terms and conditions of the GNU General Public License,
31 + * version 2, as published by the Free Software Foundation.
33 + * This program is distributed in the hope it will be useful, but WITHOUT
34 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
38 + * You should have received a copy of the GNU General Public License along with
39 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
40 + * Place - Suite 330, Boston, MA 02111-1307 USA.
43 + * Hank Janssen <hjanssen@microsoft.com>
50 +#include "RndisFilter.h"
56 +static const char* gDriverName="netvsc";
58 +// {F8615163-DF3E-46c5-913F-F2D2F965ED0E}
59 +static const GUID gNetVscDeviceType={
60 + .Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
69 + DEVICE_OBJECT *Device,
70 + void *AdditionalInfo
74 +NetVscOnDeviceRemove(
75 + DEVICE_OBJECT *Device
80 + DRIVER_OBJECT *Driver
84 +NetVscOnChannelCallback(
89 +NetVscInitializeSendBufferWithNetVsp(
90 + DEVICE_OBJECT *Device
94 +NetVscInitializeReceiveBufferWithNetVsp(
95 + DEVICE_OBJECT *Device
99 +NetVscDestroySendBuffer(
100 + NETVSC_DEVICE *NetDevice
104 +NetVscDestroyReceiveBuffer(
105 + NETVSC_DEVICE *NetDevice
110 + DEVICE_OBJECT *Device
114 +NetVscOnSendCompletion(
115 + DEVICE_OBJECT *Device,
116 + VMPACKET_DESCRIPTOR *Packet
121 + DEVICE_OBJECT *Device,
122 + NETVSC_PACKET *Packet
127 + DEVICE_OBJECT *Device,
128 + VMPACKET_DESCRIPTOR *Packet
132 +NetVscOnReceiveCompletion(
137 +NetVscSendReceiveCompletion(
138 + DEVICE_OBJECT *Device,
139 + UINT64 TransactionId
142 +static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
144 + NETVSC_DEVICE *netDevice;
146 + netDevice = MemAllocZeroed(sizeof(NETVSC_DEVICE));
150 + // Set to 2 to allow both inbound and outbound traffic
151 + InterlockedCompareExchange(&netDevice->RefCount, 2, 0);
153 + netDevice->Device = Device;
154 + Device->Extension = netDevice;
159 +static inline void FreeNetDevice(NETVSC_DEVICE *Device)
161 + ASSERT(Device->RefCount == 0);
162 + Device->Device->Extension = NULL;
167 +// Get the net device object iff exists and its refcount > 1
168 +static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT *Device)
170 + NETVSC_DEVICE *netDevice;
172 + netDevice = (NETVSC_DEVICE*)Device->Extension;
173 + if (netDevice && netDevice->RefCount > 1)
175 + InterlockedIncrement(&netDevice->RefCount);
185 +// Get the net device object iff exists and its refcount > 0
186 +static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT *Device)
188 + NETVSC_DEVICE *netDevice;
190 + netDevice = (NETVSC_DEVICE*)Device->Extension;
191 + if (netDevice && netDevice->RefCount)
193 + InterlockedIncrement(&netDevice->RefCount);
203 +static inline void PutNetDevice(DEVICE_OBJECT *Device)
205 + NETVSC_DEVICE *netDevice;
207 + netDevice = (NETVSC_DEVICE*)Device->Extension;
210 + InterlockedDecrement(&netDevice->RefCount);
213 +static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
215 + NETVSC_DEVICE *netDevice;
217 + netDevice = (NETVSC_DEVICE*)Device->Extension;
218 + if (netDevice == NULL)
221 + // Busy wait until the ref drop to 2, then set it to 1
222 + while (InterlockedCompareExchange(&netDevice->RefCount, 1, 2) != 2)
230 +static inline NETVSC_DEVICE* ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
232 + NETVSC_DEVICE *netDevice;
234 + netDevice = (NETVSC_DEVICE*)Device->Extension;
235 + if (netDevice == NULL)
238 + // Busy wait until the ref drop to 1, then set it to 0
239 + while (InterlockedCompareExchange(&netDevice->RefCount, 0, 1) != 1)
244 + Device->Extension = NULL;
263 + NETVSC_DRIVER_OBJECT* driver = (NETVSC_DRIVER_OBJECT*)drv;
266 + DPRINT_ENTER(NETVSC);
268 + DPRINT_DBG(NETVSC, "sizeof(NETVSC_PACKET)=%d, sizeof(NVSP_MESSAGE)=%d, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%d",
269 + sizeof(NETVSC_PACKET), sizeof(NVSP_MESSAGE), sizeof(VMTRANSFER_PAGE_PACKET_HEADER));
271 + // Make sure we are at least 2 pages since 1 page is used for control
272 + ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));
274 + drv->name = gDriverName;
275 + memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(GUID));
277 + // Make sure it is set by the caller
278 + ASSERT(driver->OnReceiveCallback);
279 + ASSERT(driver->OnLinkStatusChanged);
281 + // Setup the dispatch table
282 + driver->Base.OnDeviceAdd = NetVscOnDeviceAdd;
283 + driver->Base.OnDeviceRemove = NetVscOnDeviceRemove;
284 + driver->Base.OnCleanup = NetVscOnCleanup;
286 + driver->OnSend = NetVscOnSend;
288 + RndisFilterInit(driver);
290 + DPRINT_EXIT(NETVSC);
296 +NetVscInitializeReceiveBufferWithNetVsp(
297 + DEVICE_OBJECT *Device
301 + NETVSC_DEVICE *netDevice;
302 + NVSP_MESSAGE *initPacket;
304 + DPRINT_ENTER(NETVSC);
306 + netDevice = GetOutboundNetDevice(Device);
309 + DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
310 + DPRINT_EXIT(NETVSC);
313 + ASSERT(netDevice->ReceiveBufferSize > 0);
314 + ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
316 + netDevice->ReceiveBuffer = PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
317 + if (!netDevice->ReceiveBuffer)
319 + DPRINT_ERR(NETVSC, "unable to allocate receive buffer of size %d", netDevice->ReceiveBufferSize);
323 + ASSERT(((ULONG_PTR)netDevice->ReceiveBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
325 + DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
327 + // Establish the gpadl handle for this buffer on this channel.
328 + // Note: This call uses the vmbus connection rather than the channel to establish
329 + // the gpadl handle.
330 + ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
331 + netDevice->ReceiveBuffer,
332 + netDevice->ReceiveBufferSize,
333 + &netDevice->ReceiveBufferGpadlHandle);
337 + DPRINT_ERR(NETVSC, "unable to establish receive buffer's gpadl");
341 + //WaitEventWait(ext->ChannelInitEvent);
343 + // Notify the NetVsp of the gpadl handle
344 + DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
346 + initPacket = &netDevice->ChannelInitPacket;
348 + memset(initPacket, 0, sizeof(NVSP_MESSAGE));
350 + initPacket->Header.MessageType = NvspMessage1TypeSendReceiveBuffer;
351 + initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle;
352 + initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
354 + // Send the gpadl notification request
355 + ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
357 + sizeof(NVSP_MESSAGE),
358 + (ULONG_PTR)initPacket,
359 + VmbusPacketTypeDataInBand,
360 + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
363 + DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
367 + WaitEventWait(netDevice->ChannelInitEvent);
369 + // Check the response
370 + if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess)
373 + "Unable to complete receive buffer initialzation with NetVsp - status %d",
374 + initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status);
379 + // Parse the response
380 + ASSERT(netDevice->ReceiveSectionCount == 0);
381 + ASSERT(netDevice->ReceiveSections == NULL);
383 + netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections;
385 + netDevice->ReceiveSections = MemAlloc(netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
386 + if (netDevice->ReceiveSections == NULL)
392 + memcpy(netDevice->ReceiveSections,
393 + initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Sections,
394 + netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
396 + DPRINT_INFO(NETVSC,
397 + "Receive sections info (count %d, offset %d, endoffset %d, suballoc size %d, num suballocs %d)",
398 + netDevice->ReceiveSectionCount, netDevice->ReceiveSections[0].Offset, netDevice->ReceiveSections[0].EndOffset,
399 + netDevice->ReceiveSections[0].SubAllocationSize, netDevice->ReceiveSections[0].NumSubAllocations);
402 + //For 1st release, there should only be 1 section that represents the entire receive buffer
403 + if (netDevice->ReceiveSectionCount != 1 ||
404 + netDevice->ReceiveSections->Offset != 0 )
413 + NetVscDestroyReceiveBuffer(netDevice);
416 + PutNetDevice(Device);
417 + DPRINT_EXIT(NETVSC);
423 +NetVscInitializeSendBufferWithNetVsp(
424 + DEVICE_OBJECT *Device
428 + NETVSC_DEVICE *netDevice;
429 + NVSP_MESSAGE *initPacket;
431 + DPRINT_ENTER(NETVSC);
433 + netDevice = GetOutboundNetDevice(Device);
436 + DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
437 + DPRINT_EXIT(NETVSC);
440 + ASSERT(netDevice->SendBufferSize > 0);
441 + ASSERT((netDevice->SendBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
443 + netDevice->SendBuffer = PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
444 + if (!netDevice->SendBuffer)
446 + DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d", netDevice->SendBufferSize);
450 + ASSERT(((ULONG_PTR)netDevice->SendBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
452 + DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
454 + // Establish the gpadl handle for this buffer on this channel.
455 + // Note: This call uses the vmbus connection rather than the channel to establish
456 + // the gpadl handle.
457 + ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
458 + netDevice->SendBuffer,
459 + netDevice->SendBufferSize,
460 + &netDevice->SendBufferGpadlHandle);
464 + DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
468 + //WaitEventWait(ext->ChannelInitEvent);
470 + // Notify the NetVsp of the gpadl handle
471 + DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
473 + initPacket = &netDevice->ChannelInitPacket;
475 + memset(initPacket, 0, sizeof(NVSP_MESSAGE));
477 + initPacket->Header.MessageType = NvspMessage1TypeSendSendBuffer;
478 + initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle;
479 + initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID;
481 + // Send the gpadl notification request
482 + ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
484 + sizeof(NVSP_MESSAGE),
485 + (ULONG_PTR)initPacket,
486 + VmbusPacketTypeDataInBand,
487 + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
490 + DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
494 + WaitEventWait(netDevice->ChannelInitEvent);
496 + // Check the response
497 + if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess)
500 + "Unable to complete send buffer initialzation with NetVsp - status %d",
501 + initPacket->Messages.Version1Messages.SendSendBufferComplete.Status);
506 + netDevice->SendSectionSize = initPacket->Messages.Version1Messages.SendSendBufferComplete.SectionSize;
511 + NetVscDestroySendBuffer(netDevice);
514 + PutNetDevice(Device);
515 + DPRINT_EXIT(NETVSC);
520 +NetVscDestroyReceiveBuffer(
521 + NETVSC_DEVICE *NetDevice
524 + NVSP_MESSAGE *revokePacket;
528 + DPRINT_ENTER(NETVSC);
530 + // If we got a section count, it means we received a SendReceiveBufferComplete msg
531 + // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
532 + if (NetDevice->ReceiveSectionCount)
534 + DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
536 + // Send the revoke receive buffer
537 + revokePacket = &NetDevice->RevokePacket;
538 + memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
540 + revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer;
541 + revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
543 + ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
545 + sizeof(NVSP_MESSAGE),
546 + (ULONG_PTR)revokePacket,
547 + VmbusPacketTypeDataInBand,
549 + // If we failed here, we might as well return and have a leak rather than continue and a bugchk
552 + DPRINT_ERR(NETVSC, "unable to send revoke receive buffer to netvsp");
553 + DPRINT_EXIT(NETVSC);
558 + // Teardown the gpadl on the vsp end
559 + if (NetDevice->ReceiveBufferGpadlHandle)
561 + DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
563 + ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
564 + NetDevice->ReceiveBufferGpadlHandle);
566 + // If we failed here, we might as well return and have a leak rather than continue and a bugchk
569 + DPRINT_ERR(NETVSC, "unable to teardown receive buffer's gpadl");
570 + DPRINT_EXIT(NETVSC);
573 + NetDevice->ReceiveBufferGpadlHandle = 0;
576 + if (NetDevice->ReceiveBuffer)
578 + DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
580 + // Free up the receive buffer
581 + PageFree(NetDevice->ReceiveBuffer, NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
582 + NetDevice->ReceiveBuffer = NULL;
585 + if (NetDevice->ReceiveSections)
587 + MemFree(NetDevice->ReceiveSections);
588 + NetDevice->ReceiveSections = NULL;
589 + NetDevice->ReceiveSectionCount = 0;
592 + DPRINT_EXIT(NETVSC);
601 +NetVscDestroySendBuffer(
602 + NETVSC_DEVICE *NetDevice
605 + NVSP_MESSAGE *revokePacket;
609 + DPRINT_ENTER(NETVSC);
611 + // If we got a section count, it means we received a SendReceiveBufferComplete msg
612 + // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
613 + if (NetDevice->SendSectionSize)
615 + DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeSendBuffer...");
617 + // Send the revoke send buffer
618 + revokePacket = &NetDevice->RevokePacket;
619 + memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
621 + revokePacket->Header.MessageType = NvspMessage1TypeRevokeSendBuffer;
622 + revokePacket->Messages.Version1Messages.RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID;
624 + ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
626 + sizeof(NVSP_MESSAGE),
627 + (ULONG_PTR)revokePacket,
628 + VmbusPacketTypeDataInBand,
630 + // If we failed here, we might as well return and have a leak rather than continue and a bugchk
633 + DPRINT_ERR(NETVSC, "unable to send revoke send buffer to netvsp");
634 + DPRINT_EXIT(NETVSC);
639 + // Teardown the gpadl on the vsp end
640 + if (NetDevice->SendBufferGpadlHandle)
642 + DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
644 + ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
645 + NetDevice->SendBufferGpadlHandle);
647 + // If we failed here, we might as well return and have a leak rather than continue and a bugchk
650 + DPRINT_ERR(NETVSC, "unable to teardown send buffer's gpadl");
651 + DPRINT_EXIT(NETVSC);
654 + NetDevice->SendBufferGpadlHandle = 0;
657 + if (NetDevice->SendBuffer)
659 + DPRINT_INFO(NETVSC, "Freeing up send buffer...");
661 + // Free up the receive buffer
662 + PageFree(NetDevice->SendBuffer, NetDevice->SendBufferSize >> PAGE_SHIFT);
663 + NetDevice->SendBuffer = NULL;
666 + DPRINT_EXIT(NETVSC);
675 + DEVICE_OBJECT *Device
679 + NETVSC_DEVICE *netDevice;
680 + NVSP_MESSAGE *initPacket;
683 + DPRINT_ENTER(NETVSC);
685 + netDevice = GetOutboundNetDevice(Device);
688 + DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
689 + DPRINT_EXIT(NETVSC);
693 + initPacket = &netDevice->ChannelInitPacket;
695 + memset(initPacket, 0, sizeof(NVSP_MESSAGE));
696 + initPacket->Header.MessageType = NvspMessageTypeInit;
697 + initPacket->Messages.InitMessages.Init.MinProtocolVersion = NVSP_MIN_PROTOCOL_VERSION;
698 + initPacket->Messages.InitMessages.Init.MaxProtocolVersion = NVSP_MAX_PROTOCOL_VERSION;
700 + DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
702 + // Send the init request
703 + ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
705 + sizeof(NVSP_MESSAGE),
706 + (ULONG_PTR)initPacket,
707 + VmbusPacketTypeDataInBand,
708 + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
712 + DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
716 + WaitEventWait(netDevice->ChannelInitEvent);
718 + // Now, check the response
719 + //ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT);
720 + DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
721 + initPacket->Messages.InitMessages.InitComplete.Status,
722 + initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength);
724 + if (initPacket->Messages.InitMessages.InitComplete.Status != NvspStatusSuccess)
726 + DPRINT_ERR(NETVSC, "unable to initialize with netvsp (status 0x%x)", initPacket->Messages.InitMessages.InitComplete.Status);
731 + if (initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1)
733 + DPRINT_ERR(NETVSC, "unable to initialize with netvsp (version expected 1 got %d)",
734 + initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion);
738 + DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
740 + // Send the ndis version
741 + memset(initPacket, 0, sizeof(NVSP_MESSAGE));
743 + ndisVersion = 0x00050000;
745 + initPacket->Header.MessageType = NvspMessage1TypeSendNdisVersion;
746 + initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion = (ndisVersion & 0xFFFF0000) >> 16;
747 + initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion = ndisVersion & 0xFFFF;
749 + // Send the init request
750 + ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
752 + sizeof(NVSP_MESSAGE),
753 + (ULONG_PTR)initPacket,
754 + VmbusPacketTypeDataInBand,
758 + DPRINT_ERR(NETVSC, "unable to send NvspMessage1TypeSendNdisVersion");
763 + // BUGBUG - We have to wait for the above msg since the netvsp uses KMCL which acknowledges packet (completion packet)
764 + // since our Vmbus always set the VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
765 + //WaitEventWait(NetVscChannel->ChannelInitEvent);
767 + // Post the big receive buffer to NetVSP
768 + ret = NetVscInitializeReceiveBufferWithNetVsp(Device);
771 + ret = NetVscInitializeSendBufferWithNetVsp(Device);
775 + PutNetDevice(Device);
776 + DPRINT_EXIT(NETVSC);
781 +NetVscDisconnectFromVsp(
782 + NETVSC_DEVICE *NetDevice
785 + DPRINT_ENTER(NETVSC);
787 + NetVscDestroyReceiveBuffer(NetDevice);
788 + NetVscDestroySendBuffer(NetDevice);
790 + DPRINT_EXIT(NETVSC);
797 + NetVscOnDeviceAdd()
800 + Callback when the device belonging to this driver is added
805 + DEVICE_OBJECT *Device,
806 + void *AdditionalInfo
812 + NETVSC_DEVICE* netDevice;
813 + NETVSC_PACKET* packet;
816 + NETVSC_DRIVER_OBJECT *netDriver = (NETVSC_DRIVER_OBJECT*) Device->Driver;;
818 + DPRINT_ENTER(NETVSC);
820 + netDevice = AllocNetDevice(Device);
827 + DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice);
829 + // Initialize the NetVSC channel extension
830 + netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
831 + netDevice->ReceivePacketListLock = SpinlockCreate();
833 + netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
835 + INITIALIZE_LIST_HEAD(&netDevice->ReceivePacketList);
837 + for (i=0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++)
839 + packet = MemAllocZeroed(sizeof(NETVSC_PACKET) + (NETVSC_RECEIVE_SG_COUNT* sizeof(PAGE_BUFFER)));
842 + DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT, i);
846 + INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
848 + netDevice->ChannelInitEvent = WaitEventCreate();
850 + // Open the channel
851 + ret = Device->Driver->VmbusChannelInterface.Open(Device,
852 + netDriver->RingBufferSize,
853 + netDriver->RingBufferSize,
855 + NetVscOnChannelCallback,
861 + DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
866 + // Channel is opened
867 + DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
869 + // Connect with the NetVsp
870 + ret = NetVscConnectToVsp(Device);
873 + DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret);
878 + DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***", ret);
880 + DPRINT_EXIT(NETVSC);
884 + // Now, we can close the channel safely
885 + Device->Driver->VmbusChannelInterface.Close(Device);
891 + WaitEventClose(netDevice->ChannelInitEvent);
893 + while (!IsListEmpty(&netDevice->ReceivePacketList))
895 + entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
896 + packet = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
900 + SpinlockClose(netDevice->ReceivePacketListLock);
902 + ReleaseOutboundNetDevice(Device);
903 + ReleaseInboundNetDevice(Device);
905 + FreeNetDevice(netDevice);
908 + DPRINT_EXIT(NETVSC);
916 + NetVscOnDeviceRemove()
919 + Callback when the root bus device is removed
923 +NetVscOnDeviceRemove(
924 + DEVICE_OBJECT *Device
927 + NETVSC_DEVICE *netDevice;
928 + NETVSC_PACKET *netvscPacket;
932 + DPRINT_ENTER(NETVSC);
934 + DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...", Device->Extension);
936 + // Stop outbound traffic ie sends and receives completions
937 + netDevice = ReleaseOutboundNetDevice(Device);
940 + DPRINT_ERR(NETVSC, "No net device present!!");
944 + // Wait for all send completions
945 + while (netDevice->NumOutstandingSends)
947 + DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", netDevice->NumOutstandingSends);
952 + DPRINT_INFO(NETVSC, "Disconnecting from netvsp...");
954 + NetVscDisconnectFromVsp(netDevice);
956 + DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...", Device->Extension);
958 + // Stop inbound traffic ie receives and sends completions
959 + netDevice = ReleaseInboundNetDevice(Device);
961 + // At this point, no one should be accessing netDevice except in here
962 + DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice);
964 + // Now, we can close the channel safely
965 + Device->Driver->VmbusChannelInterface.Close(Device);
967 + // Release all resources
968 + while (!IsListEmpty(&netDevice->ReceivePacketList))
970 + entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
971 + netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
973 + MemFree(netvscPacket);
976 + SpinlockClose(netDevice->ReceivePacketListLock);
977 + WaitEventClose(netDevice->ChannelInitEvent);
978 + FreeNetDevice(netDevice);
980 + DPRINT_EXIT(NETVSC);
992 + Perform any cleanup when the driver is removed
1000 + DPRINT_ENTER(NETVSC);
1002 + DPRINT_EXIT(NETVSC);
1006 +NetVscOnSendCompletion(
1007 + DEVICE_OBJECT *Device,
1008 + VMPACKET_DESCRIPTOR *Packet
1011 + NETVSC_DEVICE* netDevice;
1012 + NVSP_MESSAGE *nvspPacket;
1013 + NETVSC_PACKET *nvscPacket;
1015 + DPRINT_ENTER(NETVSC);
1017 + netDevice = GetInboundNetDevice(Device);
1020 + DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1021 + DPRINT_EXIT(NETVSC);
1025 + nvspPacket = (NVSP_MESSAGE*)((ULONG_PTR)Packet + (Packet->DataOffset8 << 3));
1027 + DPRINT_DBG(NETVSC, "send completion packet - type %d", nvspPacket->Header.MessageType);
1029 + if (nvspPacket->Header.MessageType == NvspMessageTypeInitComplete ||
1030 + nvspPacket->Header.MessageType == NvspMessage1TypeSendReceiveBufferComplete ||
1031 + nvspPacket->Header.MessageType == NvspMessage1TypeSendSendBufferComplete)
1033 + // Copy the response back
1034 + memcpy(&netDevice->ChannelInitPacket, nvspPacket, sizeof(NVSP_MESSAGE));
1035 + WaitEventSet(netDevice->ChannelInitEvent);
1037 + else if (nvspPacket->Header.MessageType == NvspMessage1TypeSendRNDISPacketComplete)
1039 + // Get the send context
1040 + nvscPacket = (NETVSC_PACKET *)(ULONG_PTR)Packet->TransactionId;
1041 + ASSERT(nvscPacket);
1043 + // Notify the layer above us
1044 + nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
1046 + InterlockedDecrement(&netDevice->NumOutstandingSends);
1050 + DPRINT_ERR(NETVSC, "Unknown send completion packet type - %d received!!", nvspPacket->Header.MessageType);
1053 + PutNetDevice(Device);
1054 + DPRINT_EXIT(NETVSC);
1061 + DEVICE_OBJECT *Device,
1062 + NETVSC_PACKET *Packet
1065 + NETVSC_DEVICE* netDevice;
1068 + NVSP_MESSAGE sendMessage;
1070 + DPRINT_ENTER(NETVSC);
1072 + netDevice = GetOutboundNetDevice(Device);
1075 + DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring outbound packets", netDevice);
1076 + DPRINT_EXIT(NETVSC);
1080 + sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
1081 + if (Packet->IsDataPacket)
1082 + sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;// 0 is RMC_DATA;
1084 + sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;// 1 is RMC_CONTROL;
1086 + // Not using send buffer section
1087 + sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
1088 + sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
1090 + if (Packet->PageBufferCount)
1092 + ret = Device->Driver->VmbusChannelInterface.SendPacketPageBuffer(Device,
1093 + Packet->PageBuffers,
1094 + Packet->PageBufferCount,
1096 + sizeof(NVSP_MESSAGE),
1097 + (ULONG_PTR)Packet);
1101 + ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1103 + sizeof(NVSP_MESSAGE),
1104 + (ULONG_PTR)Packet,
1105 + VmbusPacketTypeDataInBand,
1106 + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1112 + DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d", Packet, ret);
1115 + InterlockedIncrement(&netDevice->NumOutstandingSends);
1116 + PutNetDevice(Device);
1118 + DPRINT_EXIT(NETVSC);
1125 + DEVICE_OBJECT *Device,
1126 + VMPACKET_DESCRIPTOR *Packet
1129 + NETVSC_DEVICE* netDevice;
1130 + VMTRANSFER_PAGE_PACKET_HEADER *vmxferpagePacket;
1131 + NVSP_MESSAGE *nvspPacket;
1132 + NETVSC_PACKET *netvscPacket=NULL;
1133 + LIST_ENTRY* entry;
1135 + ULONG_PTR end, endVirtual;
1136 + //NETVSC_DRIVER_OBJECT *netvscDriver;
1137 + XFERPAGE_PACKET *xferpagePacket=NULL;
1138 + LIST_ENTRY listHead;
1141 + int count=0, bytesRemain=0;
1143 + DPRINT_ENTER(NETVSC);
1145 + netDevice = GetInboundNetDevice(Device);
1148 + DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1149 + DPRINT_EXIT(NETVSC);
1153 + // All inbound packets other than send completion should be xfer page packet
1154 + if (Packet->Type != VmbusPacketTypeDataUsingTransferPages)
1156 + DPRINT_ERR(NETVSC, "Unknown packet type received - %d", Packet->Type);
1157 + PutNetDevice(Device);
1161 + nvspPacket = (NVSP_MESSAGE*)((ULONG_PTR)Packet + (Packet->DataOffset8 << 3));
1163 + // Make sure this is a valid nvsp packet
1164 + if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket )
1166 + DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d", nvspPacket->Header.MessageType);
1167 + PutNetDevice(Device);
1171 + DPRINT_DBG(NETVSC, "NVSP packet received - type %d", nvspPacket->Header.MessageType);
1173 + vmxferpagePacket = (VMTRANSFER_PAGE_PACKET_HEADER*)Packet;
1175 + if (vmxferpagePacket->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID)
1177 + DPRINT_ERR(NETVSC, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, vmxferpagePacket->TransferPageSetId);
1178 + PutNetDevice(Device);
1182 + DPRINT_DBG(NETVSC, "xfer page - range count %d", vmxferpagePacket->RangeCount);
1184 + INITIALIZE_LIST_HEAD(&listHead);
1186 + // Grab free packets (range count + 1) to represent this xfer page packet. +1 to represent
1187 + // the xfer page packet itself. We grab it here so that we know exactly how many we can fulfil
1188 + SpinlockAcquire(netDevice->ReceivePacketListLock);
1189 + while (!IsListEmpty(&netDevice->ReceivePacketList))
1191 + entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
1192 + netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1194 + INSERT_TAIL_LIST(&listHead, &netvscPacket->ListEntry);
1196 + if (++count == vmxferpagePacket->RangeCount + 1)
1199 + SpinlockRelease(netDevice->ReceivePacketListLock);
1201 + // We need at least 2 netvsc pkts (1 to represent the xfer page and at least 1 for the range)
1202 + // i.e. we can handled some of the xfer page packet ranges...
1205 + DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count, vmxferpagePacket->RangeCount+1);
1207 + // Return it to the freelist
1208 + SpinlockAcquire(netDevice->ReceivePacketListLock);
1209 + for (i=count; i != 0; i--)
1211 + entry = REMOVE_HEAD_LIST(&listHead);
1212 + netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1214 + INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &netvscPacket->ListEntry);
1216 + SpinlockRelease(netDevice->ReceivePacketListLock);
1218 + NetVscSendReceiveCompletion(Device, vmxferpagePacket->d.TransactionId);
1220 + PutNetDevice(Device);
1224 + // Remove the 1st packet to represent the xfer page packet itself
1225 + entry = REMOVE_HEAD_LIST(&listHead);
1226 + xferpagePacket = CONTAINING_RECORD(entry, XFERPAGE_PACKET, ListEntry);
1227 + xferpagePacket->Count = count - 1; // This is how much we can satisfy
1228 + ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= vmxferpagePacket->RangeCount);
1230 + if (xferpagePacket->Count != vmxferpagePacket->RangeCount)
1232 + DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket->RangeCount, xferpagePacket->Count);
1235 + // Each range represents 1 RNDIS pkt that contains 1 ethernet frame
1236 + for (i=0; i < (count - 1); i++)
1238 + entry = REMOVE_HEAD_LIST(&listHead);
1239 + netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1241 + // Initialize the netvsc packet
1242 + netvscPacket->XferPagePacket = xferpagePacket;
1243 + netvscPacket->Completion.Recv.OnReceiveCompletion = NetVscOnReceiveCompletion;
1244 + netvscPacket->Completion.Recv.ReceiveCompletionContext = netvscPacket;
1245 + netvscPacket->Device = Device;
1246 + netvscPacket->Completion.Recv.ReceiveCompletionTid = vmxferpagePacket->d.TransactionId; // Save this so that we can send it back
1248 + netvscPacket->TotalDataBufferLength = vmxferpagePacket->Ranges[i].ByteCount;
1249 + netvscPacket->PageBufferCount = 1;
1251 + ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + vmxferpagePacket->Ranges[i].ByteCount < netDevice->ReceiveBufferSize);
1253 + netvscPacket->PageBuffers[0].Length = vmxferpagePacket->Ranges[i].ByteCount;
1255 + start = GetPhysicalAddress((void*)((ULONG_PTR)netDevice->ReceiveBuffer + vmxferpagePacket->Ranges[i].ByteOffset));
1257 + netvscPacket->PageBuffers[0].Pfn = start >> PAGE_SHIFT;
1258 + endVirtual = (ULONG_PTR)netDevice->ReceiveBuffer
1259 + + vmxferpagePacket->Ranges[i].ByteOffset
1260 + + vmxferpagePacket->Ranges[i].ByteCount -1;
1261 + end = GetPhysicalAddress((void*)endVirtual);
1263 + // Calculate the page relative offset
1264 + netvscPacket->PageBuffers[0].Offset = vmxferpagePacket->Ranges[i].ByteOffset & (PAGE_SIZE -1);
1265 + if ((end >> PAGE_SHIFT) != (start>>PAGE_SHIFT)) {
1266 + //Handle frame across multiple pages:
1267 + netvscPacket->PageBuffers[0].Length =
1268 + (netvscPacket->PageBuffers[0].Pfn <<PAGE_SHIFT) + PAGE_SIZE - start;
1269 + bytesRemain = netvscPacket->TotalDataBufferLength - netvscPacket->PageBuffers[0].Length;
1270 + for (j=1; j<NETVSC_PACKET_MAXPAGE; j++) {
1271 + netvscPacket->PageBuffers[j].Offset = 0;
1272 + if (bytesRemain <= PAGE_SIZE) {
1273 + netvscPacket->PageBuffers[j].Length = bytesRemain;
1276 + netvscPacket->PageBuffers[j].Length = PAGE_SIZE;
1277 + bytesRemain -= PAGE_SIZE;
1279 + netvscPacket->PageBuffers[j].Pfn =
1280 + GetPhysicalAddress((void*)(endVirtual - bytesRemain)) >> PAGE_SHIFT;
1281 + netvscPacket->PageBufferCount++;
1282 + if (bytesRemain == 0)
1285 + ASSERT(bytesRemain == 0);
1287 + DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1289 + vmxferpagePacket->Ranges[i].ByteOffset,
1290 + vmxferpagePacket->Ranges[i].ByteCount,
1291 + netvscPacket->PageBuffers[0].Pfn,
1292 + netvscPacket->PageBuffers[0].Offset,
1293 + netvscPacket->PageBuffers[0].Length);
1295 + // Pass it to the upper layer
1296 + ((NETVSC_DRIVER_OBJECT*)Device->Driver)->OnReceiveCallback(Device, netvscPacket);
1298 + NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
1301 + ASSERT(IsListEmpty(&listHead));
1303 + PutNetDevice(Device);
1304 + DPRINT_EXIT(NETVSC);
1309 +NetVscSendReceiveCompletion(
1310 + DEVICE_OBJECT *Device,
1311 + UINT64 TransactionId
1314 + NVSP_MESSAGE recvcompMessage;
1318 + DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx", TransactionId);
1320 + recvcompMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacketComplete;
1322 + // FIXME: Pass in the status
1323 + recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
1326 + // Send the completion
1327 + ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1329 + sizeof(NVSP_MESSAGE),
1331 + VmbusPacketTypeCompletion,
1333 + if (ret == 0) // success
1337 + else if (ret == -1) // no more room...wait a bit and attempt to retry 3 times
1340 + DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId, retries);
1345 + goto retry_send_cmplt;
1349 + DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId);
1354 + DPRINT_ERR(NETVSC, "unable to send receive completion pkt - %llx", TransactionId);
1359 +// Send a receive completion packet to RNDIS device (ie NetVsp)
1362 +NetVscOnReceiveCompletion(
1365 + NETVSC_PACKET *packet = (NETVSC_PACKET*)Context;
1366 + DEVICE_OBJECT *device = (DEVICE_OBJECT*)packet->Device;
1367 + NETVSC_DEVICE* netDevice;
1368 + UINT64 transactionId=0;
1369 + BOOL fSendReceiveComp = FALSE;
1371 + DPRINT_ENTER(NETVSC);
1373 + ASSERT(packet->XferPagePacket);
1375 + // Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion,
1376 + // we are using GetInboundNetDevice() since we may have disable outbound traffic already.
1377 + netDevice = GetInboundNetDevice(device);
1380 + DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1381 + DPRINT_EXIT(NETVSC);
1385 + // Overloading use of the lock.
1386 + SpinlockAcquire(netDevice->ReceivePacketListLock);
1388 + ASSERT(packet->XferPagePacket->Count > 0);
1389 + packet->XferPagePacket->Count--;
1391 + // Last one in the line that represent 1 xfer page packet.
1392 + // Return the xfer page packet itself to the freelist
1393 + if (packet->XferPagePacket->Count == 0)
1395 + fSendReceiveComp = TRUE;
1396 + transactionId = packet->Completion.Recv.ReceiveCompletionTid;
1398 + INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->XferPagePacket->ListEntry);
1401 + // Put the packet back
1402 + INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
1403 + SpinlockRelease(netDevice->ReceivePacketListLock);
1405 + // Send a receive completion for the xfer page packet
1406 + if (fSendReceiveComp)
1408 + NetVscSendReceiveCompletion(device, transactionId);
1411 + PutNetDevice(device);
1412 + DPRINT_EXIT(NETVSC);
1418 +NetVscOnChannelCallback(
1422 + const int netPacketSize=2048;
1424 + DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
1425 + NETVSC_DEVICE *netDevice;
1427 + UINT32 bytesRecvd;
1429 + UCHAR packet[netPacketSize];
1430 + VMPACKET_DESCRIPTOR *desc;
1431 + UCHAR *buffer=packet;
1432 + int bufferlen=netPacketSize;
1435 + DPRINT_ENTER(NETVSC);
1439 + netDevice = GetInboundNetDevice(device);
1442 + DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring inbound packets", netDevice);
1443 + DPRINT_EXIT(NETVSC);
1449 + ret = device->Driver->VmbusChannelInterface.RecvPacketRaw(device,
1457 + if (bytesRecvd > 0)
1459 + DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx", bytesRecvd, requestId);
1461 + desc = (VMPACKET_DESCRIPTOR*)buffer;
1462 + switch (desc->Type)
1464 + case VmbusPacketTypeCompletion:
1465 + NetVscOnSendCompletion(device, desc);
1468 + case VmbusPacketTypeDataUsingTransferPages:
1469 + NetVscOnReceive(device, desc);
1473 + DPRINT_ERR(NETVSC, "unhandled packet type %d, tid %llx len %d\n", desc->Type, requestId, bytesRecvd);
1478 + if (bufferlen > netPacketSize)
1483 + bufferlen = netPacketSize;
1488 + //DPRINT_DBG(NETVSC, "nothing else to read...");
1491 + if (bufferlen > netPacketSize)
1496 + bufferlen = netPacketSize;
1502 + else if (ret == -2) // Handle large packet
1504 + buffer = MemAllocAtomic(bytesRecvd);
1505 + if (buffer == NULL)
1507 + // Try again next time around
1508 + DPRINT_ERR(NETVSC, "unable to allocate buffer of size (%d)!!", bytesRecvd);
1512 + bufferlen = bytesRecvd;
1520 + PutNetDevice(device);
1521 + DPRINT_EXIT(NETVSC);
1525 +++ b/drivers/staging/hv/netvsc_drv.c
1529 + * Copyright (c) 2009, Microsoft Corporation.
1531 + * This program is free software; you can redistribute it and/or modify it
1532 + * under the terms and conditions of the GNU General Public License,
1533 + * version 2, as published by the Free Software Foundation.
1535 + * This program is distributed in the hope it will be useful, but WITHOUT
1536 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1537 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1540 + * You should have received a copy of the GNU General Public License along with
1541 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
1542 + * Place - Suite 330, Boston, MA 02111-1307 USA.
1545 + * Hank Janssen <hjanssen@microsoft.com>
1550 +#include <linux/init.h>
1551 +#include <linux/module.h>
1552 +#include <linux/highmem.h>
1553 +#include <linux/device.h>
1554 +#if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
1555 +#include <asm/io.h>
1557 +#include <linux/io.h>
1559 +#include <linux/delay.h>
1560 +#include <linux/netdevice.h>
1561 +#include <linux/inetdevice.h>
1562 +#include <linux/etherdevice.h>
1563 +#include <linux/skbuff.h>
1564 +#include <linux/in.h>
1565 +#include <net/arp.h>
1566 +#include <net/route.h>
1567 +#include <net/sock.h>
1568 +#include <net/pkt_sched.h>
1570 +#include "logging.h"
1573 +#include "NetVscApi.h"
1575 +MODULE_LICENSE("GPL");
1580 +static int netvsc_probe(struct device *device);
1581 +static int netvsc_remove(struct device *device);
1582 +static int netvsc_open(struct net_device *net);
1583 +static void netvsc_xmit_completion(void *context);
1584 +static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net);
1585 +static int netvsc_recv_callback(DEVICE_OBJECT *device_obj, NETVSC_PACKET* Packet);
1586 +static int netvsc_close(struct net_device *net);
1587 +static struct net_device_stats *netvsc_get_stats(struct net_device *net);
1588 +static void netvsc_linkstatus_callback(DEVICE_OBJECT *device_obj, unsigned int status);
1593 +struct net_device_context {
1594 + struct device_context *device_ctx; // point back to our device context
1595 + struct net_device_stats stats;
1598 +struct netvsc_driver_context {
1599 + // !! These must be the first 2 fields !!
1600 + struct driver_context drv_ctx;
1601 + NETVSC_DRIVER_OBJECT drv_obj;
1608 +static int netvsc_ringbuffer_size = NETVSC_DEVICE_RING_BUFFER_SIZE;
1610 +// The one and only one
1611 +static struct netvsc_driver_context g_netvsc_drv;
1619 +Name: netvsc_drv_init()
1621 +Desc: NetVsc driver initialization
1624 +int netvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
1627 + NETVSC_DRIVER_OBJECT *net_drv_obj=&g_netvsc_drv.drv_obj;
1628 + struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;
1630 + DPRINT_ENTER(NETVSC_DRV);
1632 + vmbus_get_interface(&net_drv_obj->Base.VmbusChannelInterface);
1634 + net_drv_obj->RingBufferSize = netvsc_ringbuffer_size;
1635 + net_drv_obj->OnReceiveCallback = netvsc_recv_callback;
1636 + net_drv_obj->OnLinkStatusChanged = netvsc_linkstatus_callback;
1638 + // Callback to client driver to complete the initialization
1639 + pfn_drv_init(&net_drv_obj->Base);
1641 + drv_ctx->driver.name = net_drv_obj->Base.name;
1642 + memcpy(&drv_ctx->class_id, &net_drv_obj->Base.deviceType, sizeof(GUID));
1644 +#if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
1645 + drv_ctx->driver.probe = netvsc_probe;
1646 + drv_ctx->driver.remove = netvsc_remove;
1648 + drv_ctx->probe = netvsc_probe;
1649 + drv_ctx->remove = netvsc_remove;
1652 + // The driver belongs to vmbus
1653 + vmbus_child_driver_register(drv_ctx);
1655 + DPRINT_EXIT(NETVSC_DRV);
1662 +Name: netvsc_get_stats()
1664 +Desc: Get the network stats
1667 +static struct net_device_stats *netvsc_get_stats(struct net_device *net)
1669 + struct net_device_context *net_device_ctx = netdev_priv(net);
1671 + return &net_device_ctx->stats;
1676 +Name: netvsc_set_multicast_list()
1678 +Desc: Set the multicast list
1682 +static void netvsc_set_multicast_list(UNUSED_VAR(struct net_device *net))
1689 +Name: netvsc_probe()
1691 +Desc: Add the specified new device to this driver
1694 +static int netvsc_probe(struct device *device)
1698 + struct driver_context *driver_ctx = driver_to_driver_context(device->driver);
1699 + struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
1700 + NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
1702 + struct device_context *device_ctx = device_to_device_context(device);
1703 + DEVICE_OBJECT *device_obj = &device_ctx->device_obj;
1705 + struct net_device *net = NULL;
1706 + struct net_device_context *net_device_ctx;
1707 + NETVSC_DEVICE_INFO device_info;
1709 + DPRINT_ENTER(NETVSC_DRV);
1711 + if (!net_drv_obj->Base.OnDeviceAdd)
1716 + net = alloc_netdev(sizeof(struct net_device_context), "seth%d", ether_setup);
1717 + //net = alloc_etherdev(sizeof(struct net_device_context));
1723 + // Set initial state
1724 + netif_carrier_off(net);
1725 + netif_stop_queue(net);
1727 + net_device_ctx = netdev_priv(net);
1728 + net_device_ctx->device_ctx = device_ctx;
1729 + device->driver_data = net;
1731 + // Notify the netvsc driver of the new device
1732 + ret = net_drv_obj->Base.OnDeviceAdd(device_obj, (void*)&device_info);
1736 + device->driver_data = NULL;
1738 + DPRINT_ERR(NETVSC_DRV, "unable to add netvsc device (ret %d)", ret);
1742 + // If carrier is still off ie we did not get a link status callback, update it if necessary
1743 + // FIXME: We should use a atomic or test/set instead to avoid getting out of sync with the device's link status
1744 + if (!netif_carrier_ok(net))
1746 + if (!device_info.LinkState)
1748 + netif_carrier_on(net);
1752 + memcpy(net->dev_addr, device_info.MacAddr, ETH_ALEN);
1754 + net->open = netvsc_open;
1755 + net->hard_start_xmit = netvsc_start_xmit;
1756 + net->stop = netvsc_close;
1757 + net->get_stats = netvsc_get_stats;
1758 + net->set_multicast_list = netvsc_set_multicast_list;
1760 +#if !defined(KERNEL_2_6_27)
1761 + SET_MODULE_OWNER(net);
1763 + SET_NETDEV_DEV(net, device);
1765 + ret = register_netdev(net);
1768 + // Remove the device and release the resource
1769 + net_drv_obj->Base.OnDeviceRemove(device_obj);
1773 + DPRINT_EXIT(NETVSC_DRV);
1778 +static int netvsc_remove(struct device *device)
1781 + struct driver_context *driver_ctx = driver_to_driver_context(device->driver);
1782 + struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
1783 + NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
1785 + struct device_context *device_ctx = device_to_device_context(device);
1786 + struct net_device *net = (struct net_device *)device_ctx->device.driver_data;
1787 + DEVICE_OBJECT *device_obj = &device_ctx->device_obj;
1789 + DPRINT_ENTER(NETVSC_DRV);
1793 + DPRINT_INFO(NETVSC, "no net device to remove");
1794 + DPRINT_EXIT(NETVSC_DRV);
1798 + if (!net_drv_obj->Base.OnDeviceRemove)
1800 + DPRINT_EXIT(NETVSC_DRV);
1804 + // Stop outbound asap
1805 + netif_stop_queue(net);
1806 + //netif_carrier_off(net);
1808 + unregister_netdev(net);
1810 + // Call to the vsc driver to let it know that the device is being removed
1811 + ret = net_drv_obj->Base.OnDeviceRemove(device_obj);
1815 + DPRINT_ERR(NETVSC, "unable to remove vsc device (ret %d)", ret);
1820 + DPRINT_EXIT(NETVSC_DRV);
1827 +Name: netvsc_open()
1829 +Desc: Open the specified interface device
1832 +static int netvsc_open(struct net_device *net)
1835 + struct net_device_context *net_device_ctx = netdev_priv(net);
1836 + struct driver_context *driver_ctx = driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
1837 + struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
1838 + NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
1840 + DEVICE_OBJECT *device_obj = &net_device_ctx->device_ctx->device_obj;
1842 + DPRINT_ENTER(NETVSC_DRV);
1844 + if (netif_carrier_ok(net))
1846 + memset(&net_device_ctx->stats, 0 , sizeof(struct net_device_stats));
1848 + // Open up the device
1849 + ret = net_drv_obj->OnOpen(device_obj);
1852 + DPRINT_ERR(NETVSC_DRV, "unable to open device (ret %d).", ret);
1856 + netif_start_queue(net);
1860 + DPRINT_ERR(NETVSC_DRV, "unable to open device...link is down.");
1863 + DPRINT_EXIT(NETVSC_DRV);
1869 +Name: netvsc_close()
1871 +Desc: Close the specified interface device
1874 +static int netvsc_close(struct net_device *net)
1877 + struct net_device_context *net_device_ctx = netdev_priv(net);
1878 + struct driver_context *driver_ctx = driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
1879 + struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
1880 + NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
1882 + DEVICE_OBJECT *device_obj = &net_device_ctx->device_ctx->device_obj;
1884 + DPRINT_ENTER(NETVSC_DRV);
1886 + netif_stop_queue(net);
1888 + ret = net_drv_obj->OnClose(device_obj);
1891 + DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);
1894 + DPRINT_EXIT(NETVSC_DRV);
1902 +Name: netvsc_xmit_completion()
1904 +Desc: Send completion processing
1907 +static void netvsc_xmit_completion(void *context)
1909 + NETVSC_PACKET *packet = (NETVSC_PACKET *)context;
1910 + struct sk_buff *skb = (struct sk_buff *)(ULONG_PTR)packet->Completion.Send.SendCompletionTid;
1911 + struct net_device* net;
1913 + DPRINT_ENTER(NETVSC_DRV);
1921 + dev_kfree_skb_any(skb);
1923 + if (netif_queue_stopped(net))
1925 + DPRINT_INFO(NETVSC_DRV, "net device (%p) waking up...", net);
1927 + netif_wake_queue(net);
1931 + DPRINT_EXIT(NETVSC_DRV);
1936 +Name: netvsc_start_xmit()
1941 +static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
1944 + struct net_device_context *net_device_ctx = netdev_priv(net);
1945 + struct driver_context *driver_ctx = driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
1946 + struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
1947 + NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
1950 + NETVSC_PACKET* packet;
1954 + DPRINT_ENTER(NETVSC_DRV);
1956 + // Support only 1 chain of frags
1957 + ASSERT(skb_shinfo(skb)->frag_list == NULL);
1958 + ASSERT(skb->dev == net);
1960 + DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d", skb->len, skb->data_len);
1962 + // Add 1 for skb->data and any additional ones requested
1963 + num_frags = skb_shinfo(skb)->nr_frags + 1 + net_drv_obj->AdditionalRequestPageBufferCount;
1965 + // Allocate a netvsc packet based on # of frags.
1966 + packet = kzalloc(sizeof(NETVSC_PACKET) + (num_frags * sizeof(PAGE_BUFFER)) + net_drv_obj->RequestExtSize, GFP_ATOMIC);
1969 + DPRINT_ERR(NETVSC_DRV, "unable to allocate NETVSC_PACKET");
1973 + packet->Extension = (void*)(unsigned long)packet + sizeof(NETVSC_PACKET) + (num_frags * sizeof(PAGE_BUFFER)) ;
1975 + // Setup the rndis header
1976 + packet->PageBufferCount = num_frags;
1978 + // TODO: Flush all write buffers/ memory fence ???
1981 + // Initialize it from the skb
1982 + ASSERT(skb->data);
1983 + packet->TotalDataBufferLength = skb->len;
1985 + // Start filling in the page buffers starting at AdditionalRequestPageBufferCount offset
1986 + packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
1987 + packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Offset = (unsigned long)skb->data & (PAGE_SIZE -1);
1988 + packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Length = skb->len - skb->data_len;
1990 + ASSERT((skb->len - skb->data_len) <= PAGE_SIZE);
1992 + for (i=net_drv_obj->AdditionalRequestPageBufferCount+1; i<num_frags; i++)
1994 + packet->PageBuffers[i].Pfn = page_to_pfn(skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page);
1995 + packet->PageBuffers[i].Offset = skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page_offset;
1996 + packet->PageBuffers[i].Length = skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].size;
1999 + // Set the completion routine
2000 + packet->Completion.Send.OnSendCompletion = netvsc_xmit_completion;
2001 + packet->Completion.Send.SendCompletionContext = packet;
2002 + packet->Completion.Send.SendCompletionTid = (ULONG_PTR)skb;
2005 + ret = net_drv_obj->OnSend(&net_device_ctx->device_ctx->device_obj, packet);
2009 +#ifdef KERNEL_2_6_5
2010 +#define NETDEV_TX_OK 0
2011 +#define NETDEV_TX_BUSY 0
2013 + ret = NETDEV_TX_OK;
2014 + net_device_ctx->stats.tx_bytes += skb->len;
2015 + net_device_ctx->stats.tx_packets++;
2022 + DPRINT_ERR(NETVSC_DRV, "unable to send...retrying %d...", retries);
2027 + // no more room or we are shutting down
2028 + DPRINT_ERR(NETVSC_DRV, "unable to send (%d)...marking net device (%p) busy", ret, net);
2029 + DPRINT_INFO(NETVSC_DRV, "net device (%p) stopping", net);
2031 + ret = NETDEV_TX_BUSY;
2032 + net_device_ctx->stats.tx_dropped++;
2034 + netif_stop_queue(net);
2036 + // Null it since the caller will free it instead of the completion routine
2037 + packet->Completion.Send.SendCompletionTid = 0;
2039 + // Release the resources since we will not get any send completion
2040 + netvsc_xmit_completion((void*)packet);
2043 + DPRINT_DBG(NETVSC_DRV, "# of xmits %lu total size %lu", net_device_ctx->stats.tx_packets, net_device_ctx->stats.tx_bytes);
2045 + DPRINT_EXIT(NETVSC_DRV);
2052 +Name: netvsc_linkstatus_callback()
2054 +Desc: Link up/down notification
2057 +static void netvsc_linkstatus_callback(DEVICE_OBJECT *device_obj, unsigned int status)
2059 + struct device_context* device_ctx = to_device_context(device_obj);
2060 + struct net_device* net = (struct net_device *)device_ctx->device.driver_data;
2062 + DPRINT_ENTER(NETVSC_DRV);
2066 + DPRINT_ERR(NETVSC_DRV, "got link status but net device not initialized yet");
2072 + netif_carrier_on(net);
2073 + netif_wake_queue(net);
2077 + netif_carrier_off(net);
2078 + netif_stop_queue(net);
2080 + DPRINT_EXIT(NETVSC_DRV);
2086 +Name: netvsc_recv_callback()
2088 +Desc: Callback when we receive a packet from the "wire" on the specify device
2091 +static int netvsc_recv_callback(DEVICE_OBJECT *device_obj, NETVSC_PACKET* packet)
2094 + struct device_context *device_ctx = to_device_context(device_obj);
2095 + struct net_device *net = (struct net_device *)device_ctx->device.driver_data;
2096 + struct net_device_context *net_device_ctx;
2098 + struct sk_buff *skb;
2101 + unsigned long flags;
2103 + DPRINT_ENTER(NETVSC_DRV);
2107 + DPRINT_ERR(NETVSC_DRV, "got receive callback but net device not initialized yet");
2111 + net_device_ctx = netdev_priv(net);
2113 + // Allocate a skb - TODO preallocate this
2114 + //skb = alloc_skb(packet->TotalDataBufferLength, GFP_ATOMIC);
2115 + skb = dev_alloc_skb(packet->TotalDataBufferLength + 2); // Pad 2-bytes to align IP header to 16 bytes
2117 + skb_reserve(skb, 2);
2120 + // for kmap_atomic
2121 + local_irq_save(flags);
2123 + // Copy to skb. This copy is needed here since the memory pointed by NETVSC_PACKET
2124 + // cannot be deallocated
2125 + for (i=0; i<packet->PageBufferCount; i++)
2127 + data = kmap_atomic(pfn_to_page(packet->PageBuffers[i].Pfn), KM_IRQ1);
2128 + data = (void*)(unsigned long)data + packet->PageBuffers[i].Offset;
2130 + memcpy(skb_put(skb, packet->PageBuffers[i].Length), data, packet->PageBuffers[i].Length);
2132 + kunmap_atomic((void*)((unsigned long)data - packet->PageBuffers[i].Offset), KM_IRQ1);
2135 + local_irq_restore(flags);
2137 + skb->protocol = eth_type_trans(skb, net);
2139 + skb->ip_summed = CHECKSUM_NONE;
2141 + // Pass the skb back up. Network stack will deallocate the skb when it is done
2142 + ret = netif_rx(skb);
2147 + net_device_ctx->stats.rx_dropped++;
2150 + net_device_ctx->stats.rx_packets++;
2151 + net_device_ctx->stats.rx_bytes += skb->len;
2155 + DPRINT_DBG(NETVSC_DRV, "# of recvs %lu total size %lu", net_device_ctx->stats.rx_packets, net_device_ctx->stats.rx_bytes);
2157 + DPRINT_EXIT(NETVSC_DRV);
2162 +static int netvsc_drv_exit_cb(struct device *dev, void *data)
2164 + struct device **curr = (struct device **)data;
2166 + return 1; // stop iterating
2171 +Name: netvsc_drv_exit()
2176 +void netvsc_drv_exit(void)
2178 + NETVSC_DRIVER_OBJECT *netvsc_drv_obj=&g_netvsc_drv.drv_obj;
2179 + struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;
2181 + struct device *current_dev=NULL;
2182 +#if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
2183 +#define driver_for_each_device(drv, start, data, fn) \
2184 + struct list_head *ptr, *n; \
2185 + list_for_each_safe(ptr, n, &((drv)->devices)) {\
2186 + struct device *curr_dev;\
2187 + curr_dev = list_entry(ptr, struct device, driver_list);\
2188 + fn(curr_dev, data);\
2192 + DPRINT_ENTER(NETVSC_DRV);
2196 + current_dev = NULL;
2199 + driver_for_each_device(&drv_ctx->driver, NULL, (void*)¤t_dev, netvsc_drv_exit_cb);
2201 + if (current_dev == NULL)
2204 + // Initiate removal from the top-down
2205 + DPRINT_INFO(NETVSC_DRV, "unregistering device (%p)...", current_dev);
2207 + device_unregister(current_dev);
2210 + if (netvsc_drv_obj->Base.OnCleanup)
2211 + netvsc_drv_obj->Base.OnCleanup(&netvsc_drv_obj->Base);
2213 + vmbus_child_driver_unregister(drv_ctx);
2215 + DPRINT_EXIT(NETVSC_DRV);
2220 +static int __init netvsc_init(void)
2224 + DPRINT_ENTER(NETVSC_DRV);
2225 + DPRINT_INFO(NETVSC_DRV, "Netvsc initializing....");
2227 + ret = netvsc_drv_init(NetVscInitialize);
2229 + DPRINT_EXIT(NETVSC_DRV);
2234 +static void __exit netvsc_exit(void)
2236 + DPRINT_ENTER(NETVSC_DRV);
2238 + netvsc_drv_exit();
2240 + DPRINT_EXIT(NETVSC_DRV);
2243 +module_param(netvsc_ringbuffer_size, int, S_IRUGO);
2245 +module_init(netvsc_init);
2246 +module_exit(netvsc_exit);
2248 +++ b/drivers/staging/hv/NetVsc.h
2252 + * Copyright (c) 2009, Microsoft Corporation.
2254 + * This program is free software; you can redistribute it and/or modify it
2255 + * under the terms and conditions of the GNU General Public License,
2256 + * version 2, as published by the Free Software Foundation.
2258 + * This program is distributed in the hope it will be useful, but WITHOUT
2259 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2260 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2263 + * You should have received a copy of the GNU General Public License along with
2264 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
2265 + * Place - Suite 330, Boston, MA 02111-1307 USA.
2268 + * Hank Janssen <hjanssen@microsoft.com>
2276 +#include "VmbusPacketFormat.h"
2277 +#include "nvspprotocol.h"
2281 +#include "NetVscApi.h"
2285 +//#define NVSC_MIN_PROTOCOL_VERSION 1
2286 +//#define NVSC_MAX_PROTOCOL_VERSION 1
2288 +#define NETVSC_SEND_BUFFER_SIZE 64*1024 // 64K
2289 +#define NETVSC_SEND_BUFFER_ID 0xface
2292 +#define NETVSC_RECEIVE_BUFFER_SIZE 1024*1024 // 1MB
2294 +#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
2296 +#define NETVSC_RECEIVE_SG_COUNT 1
2298 +// Preallocated receive packets
2299 +#define NETVSC_RECEIVE_PACKETLIST_COUNT 256
2305 +// Per netvsc channel-specific
2306 +typedef struct _NETVSC_DEVICE {
2307 + DEVICE_OBJECT *Device;
2311 + int NumOutstandingSends;
2312 + // List of free preallocated NETVSC_PACKET to represent receive packet
2313 + LIST_ENTRY ReceivePacketList;
2314 + HANDLE ReceivePacketListLock;
2316 + // Send buffer allocated by us but manages by NetVSP
2318 + UINT32 SendBufferSize;
2319 + UINT32 SendBufferGpadlHandle;
2320 + UINT32 SendSectionSize;
2322 + // Receive buffer allocated by us but manages by NetVSP
2323 + PVOID ReceiveBuffer;
2324 + UINT32 ReceiveBufferSize;
2325 + UINT32 ReceiveBufferGpadlHandle;
2326 + UINT32 ReceiveSectionCount;
2327 + PNVSP_1_RECEIVE_BUFFER_SECTION ReceiveSections;
2329 + // Used for NetVSP initialization protocol
2330 + HANDLE ChannelInitEvent;
2331 + NVSP_MESSAGE ChannelInitPacket;
2333 + NVSP_MESSAGE RevokePacket;
2334 + //UCHAR HwMacAddr[HW_MACADDR_LEN];
2336 + // Holds rndis device info
2340 +#endif // _NETVSC_H_
2342 +++ b/drivers/staging/hv/RndisFilter.c
2346 + * Copyright (c) 2009, Microsoft Corporation.
2348 + * This program is free software; you can redistribute it and/or modify it
2349 + * under the terms and conditions of the GNU General Public License,
2350 + * version 2, as published by the Free Software Foundation.
2352 + * This program is distributed in the hope it will be useful, but WITHOUT
2353 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2354 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2357 + * You should have received a copy of the GNU General Public License along with
2358 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
2359 + * Place - Suite 330, Boston, MA 02111-1307 USA.
2362 + * Haiyang Zhang <haiyangz@microsoft.com>
2363 + * Hank Janssen <hjanssen@microsoft.com>
2368 +#include "logging.h"
2370 +#include "NetVscApi.h"
2371 +#include "RndisFilter.h"
2377 +typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
2378 + // The original driver
2379 + NETVSC_DRIVER_OBJECT InnerDriver;
2381 +} RNDIS_FILTER_DRIVER_OBJECT;
2384 + RNDIS_DEV_UNINITIALIZED = 0,
2385 + RNDIS_DEV_INITIALIZING,
2386 + RNDIS_DEV_INITIALIZED,
2387 + RNDIS_DEV_DATAINITIALIZED,
2388 +} RNDIS_DEVICE_STATE;
2390 +typedef struct _RNDIS_DEVICE {
2391 + NETVSC_DEVICE *NetDevice;
2393 + RNDIS_DEVICE_STATE State;
2394 + UINT32 LinkStatus;
2395 + UINT32 NewRequestId;
2397 + HANDLE RequestLock;
2398 + LIST_ENTRY RequestList;
2400 + UCHAR HwMacAddr[HW_MACADDR_LEN];
2404 +typedef struct _RNDIS_REQUEST {
2405 + LIST_ENTRY ListEntry;
2408 + // FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response,
2409 + // we can either define a max response message or add a response buffer variable above this field
2410 + RNDIS_MESSAGE ResponseMessage;
2412 + // Simplify allocation by having a netvsc packet inline
2413 + NETVSC_PACKET Packet;
2414 + PAGE_BUFFER Buffer;
2415 + // FIXME: We assumed a fixed size request here.
2416 + RNDIS_MESSAGE RequestMessage;
2420 +typedef struct _RNDIS_FILTER_PACKET {
2421 + void *CompletionContext;
2422 + PFN_ON_SENDRECVCOMPLETION OnCompletion;
2424 + RNDIS_MESSAGE Message;
2425 +} RNDIS_FILTER_PACKET;
2428 +// Internal routines
2431 +RndisFilterSendRequest(
2432 + RNDIS_DEVICE *Device,
2433 + RNDIS_REQUEST *Request
2437 +RndisFilterReceiveResponse(
2438 + RNDIS_DEVICE *Device,
2439 + RNDIS_MESSAGE *Response
2443 +RndisFilterReceiveIndicateStatus(
2444 + RNDIS_DEVICE *Device,
2445 + RNDIS_MESSAGE *Response
2449 +RndisFilterReceiveData(
2450 + RNDIS_DEVICE *Device,
2451 + RNDIS_MESSAGE *Message,
2452 + NETVSC_PACKET *Packet
2456 +RndisFilterOnReceive(
2457 + DEVICE_OBJECT *Device,
2458 + NETVSC_PACKET *Packet
2462 +RndisFilterQueryDevice(
2463 + RNDIS_DEVICE *Device,
2466 + UINT32 *ResultSize
2470 +RndisFilterQueryDeviceMac(
2471 + RNDIS_DEVICE *Device
2475 +RndisFilterQueryDeviceLinkStatus(
2476 + RNDIS_DEVICE *Device
2480 +RndisFilterSetPacketFilter(
2481 + RNDIS_DEVICE *Device,
2486 +RndisFilterInitDevice(
2487 + RNDIS_DEVICE *Device
2491 +RndisFilterOpenDevice(
2492 + RNDIS_DEVICE *Device
2496 +RndisFilterCloseDevice(
2497 + RNDIS_DEVICE *Device
2501 +RndisFilterOnDeviceAdd(
2502 + DEVICE_OBJECT *Device,
2503 + void *AdditionalInfo
2507 +RndisFilterOnDeviceRemove(
2508 + DEVICE_OBJECT *Device
2512 +RndisFilterOnCleanup(
2513 + DRIVER_OBJECT *Driver
2518 + DEVICE_OBJECT *Device
2522 +RndisFilterOnClose(
2523 + DEVICE_OBJECT *Device
2528 + DEVICE_OBJECT *Device,
2529 + NETVSC_PACKET *Packet
2533 +RndisFilterOnSendCompletion(
2538 +RndisFilterOnSendRequestCompletion(
2546 +// The one and only
2547 +RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
2549 +static inline RNDIS_DEVICE* GetRndisDevice(void)
2551 + RNDIS_DEVICE *device;
2553 + device = MemAllocZeroed(sizeof(RNDIS_DEVICE));
2559 + device->RequestLock = SpinlockCreate();
2560 + if (!device->RequestLock)
2566 + INITIALIZE_LIST_HEAD(&device->RequestList);
2568 + device->State = RNDIS_DEV_UNINITIALIZED;
2573 +static inline void PutRndisDevice(RNDIS_DEVICE *Device)
2575 + SpinlockClose(Device->RequestLock);
2579 +static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, UINT32 MessageType, UINT32 MessageLength)
2581 + RNDIS_REQUEST *request;
2582 + RNDIS_MESSAGE *rndisMessage;
2583 + RNDIS_SET_REQUEST *set;
2585 + request = MemAllocZeroed(sizeof(RNDIS_REQUEST));
2591 + request->WaitEvent = WaitEventCreate();
2592 + if (!request->WaitEvent)
2598 + rndisMessage = &request->RequestMessage;
2599 + rndisMessage->NdisMessageType = MessageType;
2600 + rndisMessage->MessageLength = MessageLength;
2602 + // Set the request id. This field is always after the rndis header for request/response packet types so
2603 + // we just used the SetRequest as a template
2604 + set = &rndisMessage->Message.SetRequest;
2605 + set->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
2607 + // Add to the request list
2608 + SpinlockAcquire(Device->RequestLock);
2609 + INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
2610 + SpinlockRelease(Device->RequestLock);
2615 +static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
2617 + SpinlockAcquire(Device->RequestLock);
2618 + REMOVE_ENTRY_LIST(&Request->ListEntry);
2619 + SpinlockRelease(Device->RequestLock);
2621 + WaitEventClose(Request->WaitEvent);
2625 +static inline void DumpRndisMessage(RNDIS_MESSAGE *RndisMessage)
2627 + switch (RndisMessage->NdisMessageType)
2629 + case REMOTE_NDIS_PACKET_MSG:
2630 + 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",
2631 + RndisMessage->MessageLength,
2632 + RndisMessage->Message.Packet.DataOffset,
2633 + RndisMessage->Message.Packet.DataLength,
2634 + RndisMessage->Message.Packet.NumOOBDataElements,
2635 + RndisMessage->Message.Packet.OOBDataOffset,
2636 + RndisMessage->Message.Packet.OOBDataLength,
2637 + RndisMessage->Message.Packet.PerPacketInfoOffset,
2638 + RndisMessage->Message.Packet.PerPacketInfoLength);
2641 + case REMOTE_NDIS_INITIALIZE_CMPLT:
2642 + 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)",
2643 + RndisMessage->MessageLength,
2644 + RndisMessage->Message.InitializeComplete.RequestId,
2645 + RndisMessage->Message.InitializeComplete.Status,
2646 + RndisMessage->Message.InitializeComplete.MajorVersion,
2647 + RndisMessage->Message.InitializeComplete.MinorVersion,
2648 + RndisMessage->Message.InitializeComplete.DeviceFlags,
2649 + RndisMessage->Message.InitializeComplete.MaxTransferSize,
2650 + RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
2651 + RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
2654 + case REMOTE_NDIS_QUERY_CMPLT:
2655 + DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT (len %u, id 0x%x, status 0x%x, buf len %u, buf offset %u)",
2656 + RndisMessage->MessageLength,
2657 + RndisMessage->Message.QueryComplete.RequestId,
2658 + RndisMessage->Message.QueryComplete.Status,
2659 + RndisMessage->Message.QueryComplete.InformationBufferLength,
2660 + RndisMessage->Message.QueryComplete.InformationBufferOffset);
2663 + case REMOTE_NDIS_SET_CMPLT:
2664 + DPRINT_DBG(NETVSC, "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
2665 + RndisMessage->MessageLength,
2666 + RndisMessage->Message.SetComplete.RequestId,
2667 + RndisMessage->Message.SetComplete.Status);
2670 + case REMOTE_NDIS_INDICATE_STATUS_MSG:
2671 + DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG (len %u, status 0x%x, buf len %u, buf offset %u)",
2672 + RndisMessage->MessageLength,
2673 + RndisMessage->Message.IndicateStatus.Status,
2674 + RndisMessage->Message.IndicateStatus.StatusBufferLength,
2675 + RndisMessage->Message.IndicateStatus.StatusBufferOffset);
2679 + DPRINT_DBG(NETVSC, "0x%x (len %u)",
2680 + RndisMessage->NdisMessageType,
2681 + RndisMessage->MessageLength);
2687 +RndisFilterSendRequest(
2688 + RNDIS_DEVICE *Device,
2689 + RNDIS_REQUEST *Request
2693 + NETVSC_PACKET *packet;
2695 + DPRINT_ENTER(NETVSC);
2697 + // Setup the packet to send it
2698 + packet = &Request->Packet;
2700 + packet->IsDataPacket = FALSE;
2701 + packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
2702 + packet->PageBufferCount = 1;
2704 + packet->PageBuffers[0].Pfn = GetPhysicalAddress(&Request->RequestMessage) >> PAGE_SHIFT;
2705 + packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
2706 + packet->PageBuffers[0].Offset = (ULONG_PTR)&Request->RequestMessage & (PAGE_SIZE -1);
2708 + packet->Completion.Send.SendCompletionContext = Request;//packet;
2709 + packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
2710 + packet->Completion.Send.SendCompletionTid = (ULONG_PTR)Device;
2712 + ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
2713 + DPRINT_EXIT(NETVSC);
2719 +RndisFilterReceiveResponse(
2720 + RNDIS_DEVICE *Device,
2721 + RNDIS_MESSAGE *Response
2724 + LIST_ENTRY *anchor;
2726 + RNDIS_REQUEST *request=NULL;
2729 + DPRINT_ENTER(NETVSC);
2731 + SpinlockAcquire(Device->RequestLock);
2732 + ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList)
2734 + request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
2736 + // All request/response message contains RequestId as the 1st field
2737 + if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
2739 + DPRINT_DBG(NETVSC, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
2740 + request->RequestMessage.Message.InitializeRequest.RequestId, request->RequestMessage.NdisMessageType, Response->NdisMessageType);
2746 + SpinlockRelease(Device->RequestLock);
2750 + if (Response->MessageLength <= sizeof(RNDIS_MESSAGE))
2752 + memcpy(&request->ResponseMessage, Response, Response->MessageLength);
2756 + DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %u)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
2758 + if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) // does not have a request id field
2760 + request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
2764 + request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
2768 + WaitEventSet(request->WaitEvent);
2772 + DPRINT_ERR(NETVSC, "no rndis request found for this response (id 0x%x res type 0x%x)",
2773 + Response->Message.InitializeComplete.RequestId, Response->NdisMessageType);
2776 + DPRINT_EXIT(NETVSC);
2780 +RndisFilterReceiveIndicateStatus(
2781 + RNDIS_DEVICE *Device,
2782 + RNDIS_MESSAGE *Response
2785 + RNDIS_INDICATE_STATUS *indicate = &Response->Message.IndicateStatus;
2787 + if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT)
2789 + gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
2791 + else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT)
2793 + gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
2802 +RndisFilterReceiveData(
2803 + RNDIS_DEVICE *Device,
2804 + RNDIS_MESSAGE *Message,
2805 + NETVSC_PACKET *Packet
2808 + RNDIS_PACKET *rndisPacket;
2809 + UINT32 dataOffset;
2811 + DPRINT_ENTER(NETVSC);
2813 + // empty ethernet frame ??
2814 + ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(RNDIS_PACKET));
2816 + rndisPacket = &Message->Message.Packet;
2818 + // FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
2819 + // netvsc packet (ie TotalDataBufferLength != MessageLength)
2821 + // Remove the rndis header and pass it back up the stack
2822 + dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
2824 + Packet->TotalDataBufferLength -= dataOffset;
2825 + Packet->PageBuffers[0].Offset += dataOffset;
2826 + Packet->PageBuffers[0].Length -= dataOffset;
2828 + Packet->IsDataPacket = TRUE;
2830 + gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device, Packet);
2832 + DPRINT_EXIT(NETVSC);
2836 +RndisFilterOnReceive(
2837 + DEVICE_OBJECT *Device,
2838 + NETVSC_PACKET *Packet
2841 + NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
2842 + RNDIS_DEVICE *rndisDevice;
2843 + RNDIS_MESSAGE rndisMessage;
2844 + RNDIS_MESSAGE *rndisHeader;
2846 + DPRINT_ENTER(NETVSC);
2848 + ASSERT(netDevice);
2849 + //Make sure the rndis device state is initialized
2850 + if (!netDevice->Extension)
2852 + DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
2853 + DPRINT_EXIT(NETVSC);
2857 + rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
2858 + if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED)
2860 + DPRINT_ERR(NETVSC, "got rndis message but rndis device uninitialized...dropping this message!");
2861 + DPRINT_EXIT(NETVSC);
2865 + rndisHeader = (RNDIS_MESSAGE*)PageMapVirtualAddress(Packet->PageBuffers[0].Pfn);
2867 + rndisHeader = (void*)((ULONG_PTR)rndisHeader + Packet->PageBuffers[0].Offset);
2869 + // Make sure we got a valid rndis message
2870 + // FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but
2871 + // the ByteCount field in the xfer page range shows 52 bytes
2873 + if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
2875 + PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
2877 + DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
2878 + rndisHeader->MessageLength, Packet->TotalDataBufferLength);
2879 + DPRINT_EXIT(NETVSC);
2884 + if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE)))
2886 + DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %u)...marking it an error!",
2887 + rndisHeader->MessageLength, sizeof(RNDIS_MESSAGE));
2890 + memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE))?sizeof(RNDIS_MESSAGE):rndisHeader->MessageLength);
2892 + PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
2894 + DumpRndisMessage(&rndisMessage);
2896 + switch (rndisMessage.NdisMessageType)
2899 + case REMOTE_NDIS_PACKET_MSG:
2900 + RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
2903 + // completion msgs
2904 + case REMOTE_NDIS_INITIALIZE_CMPLT:
2905 + case REMOTE_NDIS_QUERY_CMPLT:
2906 + case REMOTE_NDIS_SET_CMPLT:
2907 + //case REMOTE_NDIS_RESET_CMPLT:
2908 + //case REMOTE_NDIS_KEEPALIVE_CMPLT:
2909 + RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
2912 + // notification msgs
2913 + case REMOTE_NDIS_INDICATE_STATUS_MSG:
2914 + RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
2917 + DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", rndisMessage.NdisMessageType, rndisMessage.MessageLength);
2921 + DPRINT_EXIT(NETVSC);
2927 +RndisFilterQueryDevice(
2928 + RNDIS_DEVICE *Device,
2931 + UINT32 *ResultSize
2934 + RNDIS_REQUEST *request;
2935 + UINT32 inresultSize = *ResultSize;
2936 + RNDIS_QUERY_REQUEST *query;
2937 + RNDIS_QUERY_COMPLETE *queryComplete;
2940 + DPRINT_ENTER(NETVSC);
2945 + request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST));
2952 + // Setup the rndis query
2953 + query = &request->RequestMessage.Message.QueryRequest;
2955 + query->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
2956 + query->InformationBufferLength = 0;
2957 + query->DeviceVcHandle = 0;
2959 + ret = RndisFilterSendRequest(Device, request);
2965 + WaitEventWait(request->WaitEvent);
2967 + // Copy the response back
2968 + queryComplete = &request->ResponseMessage.Message.QueryComplete;
2970 + if (queryComplete->InformationBufferLength > inresultSize)
2977 + (void*)((ULONG_PTR)queryComplete + queryComplete->InformationBufferOffset),
2978 + queryComplete->InformationBufferLength);
2980 + *ResultSize = queryComplete->InformationBufferLength;
2985 + PutRndisRequest(Device, request);
2987 + DPRINT_EXIT(NETVSC);
2993 +RndisFilterQueryDeviceMac(
2994 + RNDIS_DEVICE *Device
2997 + UINT32 size=HW_MACADDR_LEN;
2999 + return RndisFilterQueryDevice(Device,
3000 + RNDIS_OID_802_3_PERMANENT_ADDRESS,
3001 + Device->HwMacAddr,
3006 +RndisFilterQueryDeviceLinkStatus(
3007 + RNDIS_DEVICE *Device
3010 + UINT32 size=sizeof(UINT32);
3012 + return RndisFilterQueryDevice(Device,
3013 + RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
3014 + &Device->LinkStatus,
3019 +RndisFilterSetPacketFilter(
3020 + RNDIS_DEVICE *Device,
3024 + RNDIS_REQUEST *request;
3025 + RNDIS_SET_REQUEST *set;
3026 + RNDIS_SET_COMPLETE *setComplete;
3030 + DPRINT_ENTER(NETVSC);
3032 + ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(UINT32) <= sizeof(RNDIS_MESSAGE));
3034 + request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(UINT32));
3041 + // Setup the rndis set
3042 + set = &request->RequestMessage.Message.SetRequest;
3043 + set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
3044 + set->InformationBufferLength = sizeof(UINT32);
3045 + set->InformationBufferOffset = sizeof(RNDIS_SET_REQUEST);
3047 + memcpy((void*)(ULONG_PTR)set + sizeof(RNDIS_SET_REQUEST), &NewFilter, sizeof(UINT32));
3049 + ret = RndisFilterSendRequest(Device, request);
3055 + ret = WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
3059 + DPRINT_ERR(NETVSC, "timeout before we got a set response...");
3060 + // We cant deallocate the request since we may still receive a send completion for it.
3069 + setComplete = &request->ResponseMessage.Message.SetComplete;
3070 + status = setComplete->Status;
3076 + PutRndisRequest(Device, request);
3079 + DPRINT_EXIT(NETVSC);
3086 + NETVSC_DRIVER_OBJECT *Driver
3089 + DPRINT_ENTER(NETVSC);
3091 + DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET));
3093 + Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
3094 + Driver->AdditionalRequestPageBufferCount = 1; // For rndis header
3096 + //Driver->Context = rndisDriver;
3098 + memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
3100 + /*rndisDriver->Driver = Driver;
3102 + ASSERT(Driver->OnLinkStatusChanged);
3103 + rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
3105 + // Save the original dispatch handlers before we override it
3106 + gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
3107 + gRndisFilter.InnerDriver.Base.OnDeviceRemove = Driver->Base.OnDeviceRemove;
3108 + gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
3110 + ASSERT(Driver->OnSend);
3111 + ASSERT(Driver->OnReceiveCallback);
3112 + gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
3113 + gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
3114 + gRndisFilter.InnerDriver.OnLinkStatusChanged = Driver->OnLinkStatusChanged;
3117 + Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
3118 + Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
3119 + Driver->Base.OnCleanup = RndisFilterOnCleanup;
3120 + Driver->OnSend = RndisFilterOnSend;
3121 + Driver->OnOpen = RndisFilterOnOpen;
3122 + Driver->OnClose = RndisFilterOnClose;
3123 + //Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus;
3124 + Driver->OnReceiveCallback = RndisFilterOnReceive;
3126 + DPRINT_EXIT(NETVSC);
3132 +RndisFilterInitDevice(
3133 + RNDIS_DEVICE *Device
3136 + RNDIS_REQUEST *request;
3137 + RNDIS_INITIALIZE_REQUEST *init;
3138 + RNDIS_INITIALIZE_COMPLETE *initComplete;
3142 + DPRINT_ENTER(NETVSC);
3144 + request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST));
3151 + // Setup the rndis set
3152 + init = &request->RequestMessage.Message.InitializeRequest;
3153 + init->MajorVersion = RNDIS_MAJOR_VERSION;
3154 + init->MinorVersion = RNDIS_MINOR_VERSION;
3155 + init->MaxTransferSize = 2048; // FIXME: Use 1536 - rounded ethernet frame size
3157 + Device->State = RNDIS_DEV_INITIALIZING;
3159 + ret = RndisFilterSendRequest(Device, request);
3162 + Device->State = RNDIS_DEV_UNINITIALIZED;
3166 + WaitEventWait(request->WaitEvent);
3168 + initComplete = &request->ResponseMessage.Message.InitializeComplete;
3169 + status = initComplete->Status;
3170 + if (status == RNDIS_STATUS_SUCCESS)
3172 + Device->State = RNDIS_DEV_INITIALIZED;
3177 + Device->State = RNDIS_DEV_UNINITIALIZED;
3184 + PutRndisRequest(Device, request);
3186 + DPRINT_EXIT(NETVSC);
3192 +RndisFilterHaltDevice(
3193 + RNDIS_DEVICE *Device
3196 + RNDIS_REQUEST *request;
3197 + RNDIS_HALT_REQUEST *halt;
3199 + DPRINT_ENTER(NETVSC);
3201 + // Attempt to do a rndis device halt
3202 + request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST));
3208 + // Setup the rndis set
3209 + halt = &request->RequestMessage.Message.HaltRequest;
3210 + halt->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
3212 + // Ignore return since this msg is optional.
3213 + RndisFilterSendRequest(Device, request);
3215 + Device->State = RNDIS_DEV_UNINITIALIZED;
3220 + PutRndisRequest(Device, request);
3222 + DPRINT_EXIT(NETVSC);
3228 +RndisFilterOpenDevice(
3229 + RNDIS_DEVICE *Device
3234 + DPRINT_ENTER(NETVSC);
3236 + if (Device->State != RNDIS_DEV_INITIALIZED)
3239 + ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
3242 + Device->State = RNDIS_DEV_DATAINITIALIZED;
3245 + DPRINT_EXIT(NETVSC);
3250 +RndisFilterCloseDevice(
3251 + RNDIS_DEVICE *Device
3256 + DPRINT_ENTER(NETVSC);
3258 + if (Device->State != RNDIS_DEV_DATAINITIALIZED)
3261 + ret = RndisFilterSetPacketFilter(Device, 0);
3264 + Device->State = RNDIS_DEV_INITIALIZED;
3267 + DPRINT_EXIT(NETVSC);
3274 +RndisFilterOnDeviceAdd(
3275 + DEVICE_OBJECT *Device,
3276 + void *AdditionalInfo
3280 + NETVSC_DEVICE *netDevice;
3281 + RNDIS_DEVICE *rndisDevice;
3282 + NETVSC_DEVICE_INFO *deviceInfo = (NETVSC_DEVICE_INFO*)AdditionalInfo;
3284 + DPRINT_ENTER(NETVSC);
3286 + //rndisDevice = MemAlloc(sizeof(RNDIS_DEVICE));
3287 + rndisDevice = GetRndisDevice();
3290 + DPRINT_EXIT(NETVSC);
3294 + DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
3296 + // Let the inner driver handle this first to create the netvsc channel
3297 + // NOTE! Once the channel is created, we may get a receive callback
3298 + // (RndisFilterOnReceive()) before this call is completed
3299 + ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
3302 + PutRndisDevice(rndisDevice);
3303 + DPRINT_EXIT(NETVSC);
3308 + // Initialize the rndis device
3310 + netDevice = (NETVSC_DEVICE*)Device->Extension;
3311 + ASSERT(netDevice);
3312 + ASSERT(netDevice->Device);
3314 + netDevice->Extension = rndisDevice;
3315 + rndisDevice->NetDevice = netDevice;
3317 + // Send the rndis initialization message
3318 + ret = RndisFilterInitDevice(rndisDevice);
3321 + // TODO: If rndis init failed, we will need to shut down the channel
3324 + // Get the mac address
3325 + ret = RndisFilterQueryDeviceMac(rndisDevice);
3328 + // TODO: shutdown rndis device and the channel
3331 + DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
3333 + rndisDevice->HwMacAddr[0],
3334 + rndisDevice->HwMacAddr[1],
3335 + rndisDevice->HwMacAddr[2],
3336 + rndisDevice->HwMacAddr[3],
3337 + rndisDevice->HwMacAddr[4],
3338 + rndisDevice->HwMacAddr[5]);
3340 + memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
3342 + RndisFilterQueryDeviceLinkStatus(rndisDevice);
3344 + deviceInfo->LinkState = rndisDevice->LinkStatus;
3345 + DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, ((deviceInfo->LinkState)?("down"):("up")));
3347 + DPRINT_EXIT(NETVSC);
3354 +RndisFilterOnDeviceRemove(
3355 + DEVICE_OBJECT *Device
3358 + NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
3359 + RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
3361 + DPRINT_ENTER(NETVSC);
3363 + // Halt and release the rndis device
3364 + RndisFilterHaltDevice(rndisDevice);
3366 + PutRndisDevice(rndisDevice);
3367 + netDevice->Extension = NULL;
3369 + // Pass control to inner driver to remove the device
3370 + gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
3372 + DPRINT_EXIT(NETVSC);
3379 +RndisFilterOnCleanup(
3380 + DRIVER_OBJECT *Driver
3383 + DPRINT_ENTER(NETVSC);
3385 + DPRINT_EXIT(NETVSC);
3390 + DEVICE_OBJECT *Device
3394 + NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
3396 + DPRINT_ENTER(NETVSC);
3398 + ASSERT(netDevice);
3399 + ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
3401 + DPRINT_EXIT(NETVSC);
3407 +RndisFilterOnClose(
3408 + DEVICE_OBJECT *Device
3412 + NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
3414 + DPRINT_ENTER(NETVSC);
3416 + ASSERT(netDevice);
3417 + ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
3419 + DPRINT_EXIT(NETVSC);
3427 + DEVICE_OBJECT *Device,
3428 + NETVSC_PACKET *Packet
3432 + RNDIS_FILTER_PACKET *filterPacket;
3433 + RNDIS_MESSAGE *rndisMessage;
3434 + RNDIS_PACKET *rndisPacket;
3435 + UINT32 rndisMessageSize;
3437 + DPRINT_ENTER(NETVSC);
3439 + // Add the rndis header
3440 + filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
3441 + ASSERT(filterPacket);
3443 + memset(filterPacket, 0, sizeof(RNDIS_FILTER_PACKET));
3445 + rndisMessage = &filterPacket->Message;
3446 + rndisMessageSize = RNDIS_MESSAGE_SIZE(RNDIS_PACKET);
3448 + rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
3449 + rndisMessage->MessageLength = Packet->TotalDataBufferLength + rndisMessageSize;
3451 + rndisPacket = &rndisMessage->Message.Packet;
3452 + rndisPacket->DataOffset = sizeof(RNDIS_PACKET);
3453 + rndisPacket->DataLength = Packet->TotalDataBufferLength;
3455 + Packet->IsDataPacket = TRUE;
3456 + Packet->PageBuffers[0].Pfn = GetPhysicalAddress(rndisMessage) >> PAGE_SHIFT;
3457 + Packet->PageBuffers[0].Offset = (ULONG_PTR)rndisMessage & (PAGE_SIZE-1);
3458 + Packet->PageBuffers[0].Length = rndisMessageSize;
3460 + // Save the packet send completion and context
3461 + filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
3462 + filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
3465 + Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
3466 + Packet->Completion.Send.SendCompletionContext = filterPacket;
3468 + ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
3471 + // Reset the completion to originals to allow retries from above
3472 + Packet->Completion.Send.OnSendCompletion = filterPacket->OnCompletion;
3473 + Packet->Completion.Send.SendCompletionContext = filterPacket->CompletionContext;
3476 + DPRINT_EXIT(NETVSC);
3482 +RndisFilterOnSendCompletion(
3485 + RNDIS_FILTER_PACKET *filterPacket = (RNDIS_FILTER_PACKET *)Context;
3487 + DPRINT_ENTER(NETVSC);
3489 + // Pass it back to the original handler
3490 + filterPacket->OnCompletion(filterPacket->CompletionContext);
3492 + DPRINT_EXIT(NETVSC);
3497 +RndisFilterOnSendRequestCompletion(
3501 + DPRINT_ENTER(NETVSC);
3504 + DPRINT_EXIT(NETVSC);
3507 +++ b/drivers/staging/hv/RndisFilter.h
3511 + * Copyright (c) 2009, Microsoft Corporation.
3513 + * This program is free software; you can redistribute it and/or modify it
3514 + * under the terms and conditions of the GNU General Public License,
3515 + * version 2, as published by the Free Software Foundation.
3517 + * This program is distributed in the hope it will be useful, but WITHOUT
3518 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3519 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
3522 + * You should have received a copy of the GNU General Public License along with
3523 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
3524 + * Place - Suite 330, Boston, MA 02111-1307 USA.
3527 + * Haiyang Zhang <haiyangz@microsoft.com>
3528 + * Hank Janssen <hjanssen@microsoft.com>
3533 +#ifndef _RNDISFILTER_H_
3534 +#define _RNDISFILTER_H_
3536 +#define __struct_bcount(x)
3539 +#include "NetVsc.h"
3543 +#define RNDIS_HEADER_SIZE (sizeof(RNDIS_MESSAGE) - sizeof(RNDIS_MESSAGE_CONTAINER))
3545 +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
3546 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
3547 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
3548 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
3549 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
3550 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
3551 +#define NDIS_PACKET_TYPE_SMT 0x00000040
3552 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
3553 +#define NDIS_PACKET_TYPE_GROUP 0x00000100
3554 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200
3555 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
3556 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
3565 + NETVSC_DRIVER_OBJECT *Driver
3569 +#endif // _RNDISFILTER_H_