]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/staging-hv-add-the-hyper-v-virtual-network-driver.patch
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / staging-hv-add-the-hyper-v-virtual-network-driver.patch
CommitLineData
2cb7cef9
BS
1From fec8755b6193c93a935423fdd6026b354aa2e15e Mon Sep 17 00:00:00 2001
2From: Hank Janssen <hjanssen@microsoft.com>
3Date: Mon, 13 Jul 2009 15:34:54 -0700
4Subject: Staging: hv: add the Hyper-V virtual network driver
5
6From: Hank Janssen <hjanssen@microsoft.com>
7
8This is the virtual network driver when running Linux on top of Hyper-V.
9
10Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
11Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
12Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
13---
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
21
22--- /dev/null
23+++ b/drivers/staging/hv/NetVsc.c
24@@ -0,0 +1,1499 @@
25+/*
26+ *
27+ * Copyright (c) 2009, Microsoft Corporation.
28+ *
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.
32+ *
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
36+ * more details.
37+ *
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.
41+ *
42+ * Authors:
43+ * Hank Janssen <hjanssen@microsoft.com>
44+ *
45+ */
46+
47+
48+#include "logging.h"
49+#include "NetVsc.h"
50+#include "RndisFilter.h"
51+
52+
53+//
54+// Globals
55+//
56+static const char* gDriverName="netvsc";
57+
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}
61+};
62+
63+
64+//
65+// Internal routines
66+//
67+static int
68+NetVscOnDeviceAdd(
69+ DEVICE_OBJECT *Device,
70+ void *AdditionalInfo
71+ );
72+
73+static int
74+NetVscOnDeviceRemove(
75+ DEVICE_OBJECT *Device
76+ );
77+
78+static void
79+NetVscOnCleanup(
80+ DRIVER_OBJECT *Driver
81+ );
82+
83+static void
84+NetVscOnChannelCallback(
85+ PVOID context
86+ );
87+
88+static int
89+NetVscInitializeSendBufferWithNetVsp(
90+ DEVICE_OBJECT *Device
91+ );
92+
93+static int
94+NetVscInitializeReceiveBufferWithNetVsp(
95+ DEVICE_OBJECT *Device
96+ );
97+
98+static int
99+NetVscDestroySendBuffer(
100+ NETVSC_DEVICE *NetDevice
101+ );
102+
103+static int
104+NetVscDestroyReceiveBuffer(
105+ NETVSC_DEVICE *NetDevice
106+ );
107+
108+static int
109+NetVscConnectToVsp(
110+ DEVICE_OBJECT *Device
111+ );
112+
113+static void
114+NetVscOnSendCompletion(
115+ DEVICE_OBJECT *Device,
116+ VMPACKET_DESCRIPTOR *Packet
117+ );
118+
119+static int
120+NetVscOnSend(
121+ DEVICE_OBJECT *Device,
122+ NETVSC_PACKET *Packet
123+ );
124+
125+static void
126+NetVscOnReceive(
127+ DEVICE_OBJECT *Device,
128+ VMPACKET_DESCRIPTOR *Packet
129+ );
130+
131+static void
132+NetVscOnReceiveCompletion(
133+ PVOID Context
134+ );
135+
136+static void
137+NetVscSendReceiveCompletion(
138+ DEVICE_OBJECT *Device,
139+ UINT64 TransactionId
140+ );
141+
142+static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
143+{
144+ NETVSC_DEVICE *netDevice;
145+
146+ netDevice = MemAllocZeroed(sizeof(NETVSC_DEVICE));
147+ if (!netDevice)
148+ return NULL;
149+
150+ // Set to 2 to allow both inbound and outbound traffic
151+ InterlockedCompareExchange(&netDevice->RefCount, 2, 0);
152+
153+ netDevice->Device = Device;
154+ Device->Extension = netDevice;
155+
156+ return netDevice;
157+}
158+
159+static inline void FreeNetDevice(NETVSC_DEVICE *Device)
160+{
161+ ASSERT(Device->RefCount == 0);
162+ Device->Device->Extension = NULL;
163+ MemFree(Device);
164+}
165+
166+
167+// Get the net device object iff exists and its refcount > 1
168+static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT *Device)
169+{
170+ NETVSC_DEVICE *netDevice;
171+
172+ netDevice = (NETVSC_DEVICE*)Device->Extension;
173+ if (netDevice && netDevice->RefCount > 1)
174+ {
175+ InterlockedIncrement(&netDevice->RefCount);
176+ }
177+ else
178+ {
179+ netDevice = NULL;
180+ }
181+
182+ return netDevice;
183+}
184+
185+// Get the net device object iff exists and its refcount > 0
186+static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT *Device)
187+{
188+ NETVSC_DEVICE *netDevice;
189+
190+ netDevice = (NETVSC_DEVICE*)Device->Extension;
191+ if (netDevice && netDevice->RefCount)
192+ {
193+ InterlockedIncrement(&netDevice->RefCount);
194+ }
195+ else
196+ {
197+ netDevice = NULL;
198+ }
199+
200+ return netDevice;
201+}
202+
203+static inline void PutNetDevice(DEVICE_OBJECT *Device)
204+{
205+ NETVSC_DEVICE *netDevice;
206+
207+ netDevice = (NETVSC_DEVICE*)Device->Extension;
208+ ASSERT(netDevice);
209+
210+ InterlockedDecrement(&netDevice->RefCount);
211+}
212+
213+static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
214+{
215+ NETVSC_DEVICE *netDevice;
216+
217+ netDevice = (NETVSC_DEVICE*)Device->Extension;
218+ if (netDevice == NULL)
219+ return NULL;
220+
221+ // Busy wait until the ref drop to 2, then set it to 1
222+ while (InterlockedCompareExchange(&netDevice->RefCount, 1, 2) != 2)
223+ {
224+ Sleep(100);
225+ }
226+
227+ return netDevice;
228+}
229+
230+static inline NETVSC_DEVICE* ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
231+{
232+ NETVSC_DEVICE *netDevice;
233+
234+ netDevice = (NETVSC_DEVICE*)Device->Extension;
235+ if (netDevice == NULL)
236+ return NULL;
237+
238+ // Busy wait until the ref drop to 1, then set it to 0
239+ while (InterlockedCompareExchange(&netDevice->RefCount, 0, 1) != 1)
240+ {
241+ Sleep(100);
242+ }
243+
244+ Device->Extension = NULL;
245+ return netDevice;
246+}
247+
248+/*++;
249+
250+
251+Name:
252+ NetVscInitialize()
253+
254+Description:
255+ Main entry point
256+
257+--*/
258+int
259+NetVscInitialize(
260+ DRIVER_OBJECT *drv
261+ )
262+{
263+ NETVSC_DRIVER_OBJECT* driver = (NETVSC_DRIVER_OBJECT*)drv;
264+ int ret=0;
265+
266+ DPRINT_ENTER(NETVSC);
267+
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));
270+
271+ // Make sure we are at least 2 pages since 1 page is used for control
272+ ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));
273+
274+ drv->name = gDriverName;
275+ memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(GUID));
276+
277+ // Make sure it is set by the caller
278+ ASSERT(driver->OnReceiveCallback);
279+ ASSERT(driver->OnLinkStatusChanged);
280+
281+ // Setup the dispatch table
282+ driver->Base.OnDeviceAdd = NetVscOnDeviceAdd;
283+ driver->Base.OnDeviceRemove = NetVscOnDeviceRemove;
284+ driver->Base.OnCleanup = NetVscOnCleanup;
285+
286+ driver->OnSend = NetVscOnSend;
287+
288+ RndisFilterInit(driver);
289+
290+ DPRINT_EXIT(NETVSC);
291+
292+ return ret;
293+}
294+
295+static int
296+NetVscInitializeReceiveBufferWithNetVsp(
297+ DEVICE_OBJECT *Device
298+ )
299+{
300+ int ret=0;
301+ NETVSC_DEVICE *netDevice;
302+ NVSP_MESSAGE *initPacket;
303+
304+ DPRINT_ENTER(NETVSC);
305+
306+ netDevice = GetOutboundNetDevice(Device);
307+ if (!netDevice)
308+ {
309+ DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
310+ DPRINT_EXIT(NETVSC);
311+ return -1;
312+ }
313+ ASSERT(netDevice->ReceiveBufferSize > 0);
314+ ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
315+
316+ netDevice->ReceiveBuffer = PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
317+ if (!netDevice->ReceiveBuffer)
318+ {
319+ DPRINT_ERR(NETVSC, "unable to allocate receive buffer of size %d", netDevice->ReceiveBufferSize);
320+ ret = -1;
321+ goto Cleanup;
322+ }
323+ ASSERT(((ULONG_PTR)netDevice->ReceiveBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
324+
325+ DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
326+
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);
334+
335+ if (ret != 0)
336+ {
337+ DPRINT_ERR(NETVSC, "unable to establish receive buffer's gpadl");
338+ goto Cleanup;
339+ }
340+
341+ //WaitEventWait(ext->ChannelInitEvent);
342+
343+ // Notify the NetVsp of the gpadl handle
344+ DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
345+
346+ initPacket = &netDevice->ChannelInitPacket;
347+
348+ memset(initPacket, 0, sizeof(NVSP_MESSAGE));
349+
350+ initPacket->Header.MessageType = NvspMessage1TypeSendReceiveBuffer;
351+ initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle;
352+ initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
353+
354+ // Send the gpadl notification request
355+ ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
356+ initPacket,
357+ sizeof(NVSP_MESSAGE),
358+ (ULONG_PTR)initPacket,
359+ VmbusPacketTypeDataInBand,
360+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
361+ if (ret != 0)
362+ {
363+ DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
364+ goto Cleanup;
365+ }
366+
367+ WaitEventWait(netDevice->ChannelInitEvent);
368+
369+ // Check the response
370+ if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess)
371+ {
372+ DPRINT_ERR(NETVSC,
373+ "Unable to complete receive buffer initialzation with NetVsp - status %d",
374+ initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status);
375+ ret = -1;
376+ goto Cleanup;
377+ }
378+
379+ // Parse the response
380+ ASSERT(netDevice->ReceiveSectionCount == 0);
381+ ASSERT(netDevice->ReceiveSections == NULL);
382+
383+ netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections;
384+
385+ netDevice->ReceiveSections = MemAlloc(netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
386+ if (netDevice->ReceiveSections == NULL)
387+ {
388+ ret = -1;
389+ goto Cleanup;
390+ }
391+
392+ memcpy(netDevice->ReceiveSections,
393+ initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Sections,
394+ netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
395+
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);
400+
401+
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 )
405+ {
406+ ret = -1;
407+ goto Cleanup;
408+ }
409+
410+ goto Exit;
411+
412+Cleanup:
413+ NetVscDestroyReceiveBuffer(netDevice);
414+
415+Exit:
416+ PutNetDevice(Device);
417+ DPRINT_EXIT(NETVSC);
418+ return ret;
419+}
420+
421+
422+static int
423+NetVscInitializeSendBufferWithNetVsp(
424+ DEVICE_OBJECT *Device
425+ )
426+{
427+ int ret=0;
428+ NETVSC_DEVICE *netDevice;
429+ NVSP_MESSAGE *initPacket;
430+
431+ DPRINT_ENTER(NETVSC);
432+
433+ netDevice = GetOutboundNetDevice(Device);
434+ if (!netDevice)
435+ {
436+ DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
437+ DPRINT_EXIT(NETVSC);
438+ return -1;
439+ }
440+ ASSERT(netDevice->SendBufferSize > 0);
441+ ASSERT((netDevice->SendBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
442+
443+ netDevice->SendBuffer = PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
444+ if (!netDevice->SendBuffer)
445+ {
446+ DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d", netDevice->SendBufferSize);
447+ ret = -1;
448+ goto Cleanup;
449+ }
450+ ASSERT(((ULONG_PTR)netDevice->SendBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
451+
452+ DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
453+
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);
461+
462+ if (ret != 0)
463+ {
464+ DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
465+ goto Cleanup;
466+ }
467+
468+ //WaitEventWait(ext->ChannelInitEvent);
469+
470+ // Notify the NetVsp of the gpadl handle
471+ DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
472+
473+ initPacket = &netDevice->ChannelInitPacket;
474+
475+ memset(initPacket, 0, sizeof(NVSP_MESSAGE));
476+
477+ initPacket->Header.MessageType = NvspMessage1TypeSendSendBuffer;
478+ initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle;
479+ initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID;
480+
481+ // Send the gpadl notification request
482+ ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
483+ initPacket,
484+ sizeof(NVSP_MESSAGE),
485+ (ULONG_PTR)initPacket,
486+ VmbusPacketTypeDataInBand,
487+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
488+ if (ret != 0)
489+ {
490+ DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
491+ goto Cleanup;
492+ }
493+
494+ WaitEventWait(netDevice->ChannelInitEvent);
495+
496+ // Check the response
497+ if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess)
498+ {
499+ DPRINT_ERR(NETVSC,
500+ "Unable to complete send buffer initialzation with NetVsp - status %d",
501+ initPacket->Messages.Version1Messages.SendSendBufferComplete.Status);
502+ ret = -1;
503+ goto Cleanup;
504+ }
505+
506+ netDevice->SendSectionSize = initPacket->Messages.Version1Messages.SendSendBufferComplete.SectionSize;
507+
508+ goto Exit;
509+
510+Cleanup:
511+ NetVscDestroySendBuffer(netDevice);
512+
513+Exit:
514+ PutNetDevice(Device);
515+ DPRINT_EXIT(NETVSC);
516+ return ret;
517+}
518+
519+static int
520+NetVscDestroyReceiveBuffer(
521+ NETVSC_DEVICE *NetDevice
522+ )
523+{
524+ NVSP_MESSAGE *revokePacket;
525+ int ret=0;
526+
527+
528+ DPRINT_ENTER(NETVSC);
529+
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)
533+ {
534+ DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
535+
536+ // Send the revoke receive buffer
537+ revokePacket = &NetDevice->RevokePacket;
538+ memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
539+
540+ revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer;
541+ revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
542+
543+ ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
544+ revokePacket,
545+ sizeof(NVSP_MESSAGE),
546+ (ULONG_PTR)revokePacket,
547+ VmbusPacketTypeDataInBand,
548+ 0);
549+ // If we failed here, we might as well return and have a leak rather than continue and a bugchk
550+ if (ret != 0)
551+ {
552+ DPRINT_ERR(NETVSC, "unable to send revoke receive buffer to netvsp");
553+ DPRINT_EXIT(NETVSC);
554+ return -1;
555+ }
556+ }
557+
558+ // Teardown the gpadl on the vsp end
559+ if (NetDevice->ReceiveBufferGpadlHandle)
560+ {
561+ DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
562+
563+ ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
564+ NetDevice->ReceiveBufferGpadlHandle);
565+
566+ // If we failed here, we might as well return and have a leak rather than continue and a bugchk
567+ if (ret != 0)
568+ {
569+ DPRINT_ERR(NETVSC, "unable to teardown receive buffer's gpadl");
570+ DPRINT_EXIT(NETVSC);
571+ return -1;
572+ }
573+ NetDevice->ReceiveBufferGpadlHandle = 0;
574+ }
575+
576+ if (NetDevice->ReceiveBuffer)
577+ {
578+ DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
579+
580+ // Free up the receive buffer
581+ PageFree(NetDevice->ReceiveBuffer, NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
582+ NetDevice->ReceiveBuffer = NULL;
583+ }
584+
585+ if (NetDevice->ReceiveSections)
586+ {
587+ MemFree(NetDevice->ReceiveSections);
588+ NetDevice->ReceiveSections = NULL;
589+ NetDevice->ReceiveSectionCount = 0;
590+ }
591+
592+ DPRINT_EXIT(NETVSC);
593+
594+ return ret;
595+}
596+
597+
598+
599+
600+static int
601+NetVscDestroySendBuffer(
602+ NETVSC_DEVICE *NetDevice
603+ )
604+{
605+ NVSP_MESSAGE *revokePacket;
606+ int ret=0;
607+
608+
609+ DPRINT_ENTER(NETVSC);
610+
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)
614+ {
615+ DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeSendBuffer...");
616+
617+ // Send the revoke send buffer
618+ revokePacket = &NetDevice->RevokePacket;
619+ memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
620+
621+ revokePacket->Header.MessageType = NvspMessage1TypeRevokeSendBuffer;
622+ revokePacket->Messages.Version1Messages.RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID;
623+
624+ ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
625+ revokePacket,
626+ sizeof(NVSP_MESSAGE),
627+ (ULONG_PTR)revokePacket,
628+ VmbusPacketTypeDataInBand,
629+ 0);
630+ // If we failed here, we might as well return and have a leak rather than continue and a bugchk
631+ if (ret != 0)
632+ {
633+ DPRINT_ERR(NETVSC, "unable to send revoke send buffer to netvsp");
634+ DPRINT_EXIT(NETVSC);
635+ return -1;
636+ }
637+ }
638+
639+ // Teardown the gpadl on the vsp end
640+ if (NetDevice->SendBufferGpadlHandle)
641+ {
642+ DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
643+
644+ ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
645+ NetDevice->SendBufferGpadlHandle);
646+
647+ // If we failed here, we might as well return and have a leak rather than continue and a bugchk
648+ if (ret != 0)
649+ {
650+ DPRINT_ERR(NETVSC, "unable to teardown send buffer's gpadl");
651+ DPRINT_EXIT(NETVSC);
652+ return -1;
653+ }
654+ NetDevice->SendBufferGpadlHandle = 0;
655+ }
656+
657+ if (NetDevice->SendBuffer)
658+ {
659+ DPRINT_INFO(NETVSC, "Freeing up send buffer...");
660+
661+ // Free up the receive buffer
662+ PageFree(NetDevice->SendBuffer, NetDevice->SendBufferSize >> PAGE_SHIFT);
663+ NetDevice->SendBuffer = NULL;
664+ }
665+
666+ DPRINT_EXIT(NETVSC);
667+
668+ return ret;
669+}
670+
671+
672+
673+static int
674+NetVscConnectToVsp(
675+ DEVICE_OBJECT *Device
676+ )
677+{
678+ int ret=0;
679+ NETVSC_DEVICE *netDevice;
680+ NVSP_MESSAGE *initPacket;
681+ int ndisVersion;
682+
683+ DPRINT_ENTER(NETVSC);
684+
685+ netDevice = GetOutboundNetDevice(Device);
686+ if (!netDevice)
687+ {
688+ DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
689+ DPRINT_EXIT(NETVSC);
690+ return -1;
691+ }
692+
693+ initPacket = &netDevice->ChannelInitPacket;
694+
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;
699+
700+ DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
701+
702+ // Send the init request
703+ ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
704+ initPacket,
705+ sizeof(NVSP_MESSAGE),
706+ (ULONG_PTR)initPacket,
707+ VmbusPacketTypeDataInBand,
708+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
709+
710+ if( ret != 0)
711+ {
712+ DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
713+ goto Cleanup;
714+ }
715+
716+ WaitEventWait(netDevice->ChannelInitEvent);
717+
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);
723+
724+ if (initPacket->Messages.InitMessages.InitComplete.Status != NvspStatusSuccess)
725+ {
726+ DPRINT_ERR(NETVSC, "unable to initialize with netvsp (status 0x%x)", initPacket->Messages.InitMessages.InitComplete.Status);
727+ ret = -1;
728+ goto Cleanup;
729+ }
730+
731+ if (initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1)
732+ {
733+ DPRINT_ERR(NETVSC, "unable to initialize with netvsp (version expected 1 got %d)",
734+ initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion);
735+ ret = -1;
736+ goto Cleanup;
737+ }
738+ DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
739+
740+ // Send the ndis version
741+ memset(initPacket, 0, sizeof(NVSP_MESSAGE));
742+
743+ ndisVersion = 0x00050000;
744+
745+ initPacket->Header.MessageType = NvspMessage1TypeSendNdisVersion;
746+ initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion = (ndisVersion & 0xFFFF0000) >> 16;
747+ initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion = ndisVersion & 0xFFFF;
748+
749+ // Send the init request
750+ ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
751+ initPacket,
752+ sizeof(NVSP_MESSAGE),
753+ (ULONG_PTR)initPacket,
754+ VmbusPacketTypeDataInBand,
755+ 0);
756+ if (ret != 0)
757+ {
758+ DPRINT_ERR(NETVSC, "unable to send NvspMessage1TypeSendNdisVersion");
759+ ret = -1;
760+ goto Cleanup;
761+ }
762+ //
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);
766+
767+ // Post the big receive buffer to NetVSP
768+ ret = NetVscInitializeReceiveBufferWithNetVsp(Device);
769+ if (ret == 0)
770+ {
771+ ret = NetVscInitializeSendBufferWithNetVsp(Device);
772+ }
773+
774+Cleanup:
775+ PutNetDevice(Device);
776+ DPRINT_EXIT(NETVSC);
777+ return ret;
778+}
779+
780+static void
781+NetVscDisconnectFromVsp(
782+ NETVSC_DEVICE *NetDevice
783+ )
784+{
785+ DPRINT_ENTER(NETVSC);
786+
787+ NetVscDestroyReceiveBuffer(NetDevice);
788+ NetVscDestroySendBuffer(NetDevice);
789+
790+ DPRINT_EXIT(NETVSC);
791+}
792+
793+
794+/*++
795+
796+Name:
797+ NetVscOnDeviceAdd()
798+
799+Description:
800+ Callback when the device belonging to this driver is added
801+
802+--*/
803+int
804+NetVscOnDeviceAdd(
805+ DEVICE_OBJECT *Device,
806+ void *AdditionalInfo
807+ )
808+{
809+ int ret=0;
810+ int i;
811+
812+ NETVSC_DEVICE* netDevice;
813+ NETVSC_PACKET* packet;
814+ LIST_ENTRY *entry;
815+
816+ NETVSC_DRIVER_OBJECT *netDriver = (NETVSC_DRIVER_OBJECT*) Device->Driver;;
817+
818+ DPRINT_ENTER(NETVSC);
819+
820+ netDevice = AllocNetDevice(Device);
821+ if (!netDevice)
822+ {
823+ ret = -1;
824+ goto Cleanup;
825+ }
826+
827+ DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice);
828+
829+ // Initialize the NetVSC channel extension
830+ netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
831+ netDevice->ReceivePacketListLock = SpinlockCreate();
832+
833+ netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
834+
835+ INITIALIZE_LIST_HEAD(&netDevice->ReceivePacketList);
836+
837+ for (i=0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++)
838+ {
839+ packet = MemAllocZeroed(sizeof(NETVSC_PACKET) + (NETVSC_RECEIVE_SG_COUNT* sizeof(PAGE_BUFFER)));
840+ if (!packet)
841+ {
842+ DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT, i);
843+ break;
844+ }
845+
846+ INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
847+ }
848+ netDevice->ChannelInitEvent = WaitEventCreate();
849+
850+ // Open the channel
851+ ret = Device->Driver->VmbusChannelInterface.Open(Device,
852+ netDriver->RingBufferSize,
853+ netDriver->RingBufferSize,
854+ NULL, 0,
855+ NetVscOnChannelCallback,
856+ Device
857+ );
858+
859+ if (ret != 0)
860+ {
861+ DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
862+ ret = -1;
863+ goto Cleanup;
864+ }
865+
866+ // Channel is opened
867+ DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
868+
869+ // Connect with the NetVsp
870+ ret = NetVscConnectToVsp(Device);
871+ if (ret != 0)
872+ {
873+ DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret);
874+ ret = -1;
875+ goto Close;
876+ }
877+
878+ DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***", ret);
879+
880+ DPRINT_EXIT(NETVSC);
881+ return ret;
882+
883+Close:
884+ // Now, we can close the channel safely
885+ Device->Driver->VmbusChannelInterface.Close(Device);
886+
887+Cleanup:
888+
889+ if (netDevice)
890+ {
891+ WaitEventClose(netDevice->ChannelInitEvent);
892+
893+ while (!IsListEmpty(&netDevice->ReceivePacketList))
894+ {
895+ entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
896+ packet = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
897+ MemFree(packet);
898+ }
899+
900+ SpinlockClose(netDevice->ReceivePacketListLock);
901+
902+ ReleaseOutboundNetDevice(Device);
903+ ReleaseInboundNetDevice(Device);
904+
905+ FreeNetDevice(netDevice);
906+ }
907+
908+ DPRINT_EXIT(NETVSC);
909+ return ret;
910+}
911+
912+
913+/*++
914+
915+Name:
916+ NetVscOnDeviceRemove()
917+
918+Description:
919+ Callback when the root bus device is removed
920+
921+--*/
922+int
923+NetVscOnDeviceRemove(
924+ DEVICE_OBJECT *Device
925+ )
926+{
927+ NETVSC_DEVICE *netDevice;
928+ NETVSC_PACKET *netvscPacket;
929+ int ret=0;
930+ LIST_ENTRY *entry;
931+
932+ DPRINT_ENTER(NETVSC);
933+
934+ DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...", Device->Extension);
935+
936+ // Stop outbound traffic ie sends and receives completions
937+ netDevice = ReleaseOutboundNetDevice(Device);
938+ if (!netDevice)
939+ {
940+ DPRINT_ERR(NETVSC, "No net device present!!");
941+ return -1;
942+ }
943+
944+ // Wait for all send completions
945+ while (netDevice->NumOutstandingSends)
946+ {
947+ DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", netDevice->NumOutstandingSends);
948+
949+ Sleep(100);
950+ }
951+
952+ DPRINT_INFO(NETVSC, "Disconnecting from netvsp...");
953+
954+ NetVscDisconnectFromVsp(netDevice);
955+
956+ DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...", Device->Extension);
957+
958+ // Stop inbound traffic ie receives and sends completions
959+ netDevice = ReleaseInboundNetDevice(Device);
960+
961+ // At this point, no one should be accessing netDevice except in here
962+ DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice);
963+
964+ // Now, we can close the channel safely
965+ Device->Driver->VmbusChannelInterface.Close(Device);
966+
967+ // Release all resources
968+ while (!IsListEmpty(&netDevice->ReceivePacketList))
969+ {
970+ entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
971+ netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
972+
973+ MemFree(netvscPacket);
974+ }
975+
976+ SpinlockClose(netDevice->ReceivePacketListLock);
977+ WaitEventClose(netDevice->ChannelInitEvent);
978+ FreeNetDevice(netDevice);
979+
980+ DPRINT_EXIT(NETVSC);
981+ return ret;
982+}
983+
984+
985+
986+/*++
987+
988+Name:
989+ NetVscOnCleanup()
990+
991+Description:
992+ Perform any cleanup when the driver is removed
993+
994+--*/
995+void
996+NetVscOnCleanup(
997+ DRIVER_OBJECT *drv
998+ )
999+{
1000+ DPRINT_ENTER(NETVSC);
1001+
1002+ DPRINT_EXIT(NETVSC);
1003+}
1004+
1005+static void
1006+NetVscOnSendCompletion(
1007+ DEVICE_OBJECT *Device,
1008+ VMPACKET_DESCRIPTOR *Packet
1009+ )
1010+{
1011+ NETVSC_DEVICE* netDevice;
1012+ NVSP_MESSAGE *nvspPacket;
1013+ NETVSC_PACKET *nvscPacket;
1014+
1015+ DPRINT_ENTER(NETVSC);
1016+
1017+ netDevice = GetInboundNetDevice(Device);
1018+ if (!netDevice)
1019+ {
1020+ DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1021+ DPRINT_EXIT(NETVSC);
1022+ return;
1023+ }
1024+
1025+ nvspPacket = (NVSP_MESSAGE*)((ULONG_PTR)Packet + (Packet->DataOffset8 << 3));
1026+
1027+ DPRINT_DBG(NETVSC, "send completion packet - type %d", nvspPacket->Header.MessageType);
1028+
1029+ if (nvspPacket->Header.MessageType == NvspMessageTypeInitComplete ||
1030+ nvspPacket->Header.MessageType == NvspMessage1TypeSendReceiveBufferComplete ||
1031+ nvspPacket->Header.MessageType == NvspMessage1TypeSendSendBufferComplete)
1032+ {
1033+ // Copy the response back
1034+ memcpy(&netDevice->ChannelInitPacket, nvspPacket, sizeof(NVSP_MESSAGE));
1035+ WaitEventSet(netDevice->ChannelInitEvent);
1036+ }
1037+ else if (nvspPacket->Header.MessageType == NvspMessage1TypeSendRNDISPacketComplete)
1038+ {
1039+ // Get the send context
1040+ nvscPacket = (NETVSC_PACKET *)(ULONG_PTR)Packet->TransactionId;
1041+ ASSERT(nvscPacket);
1042+
1043+ // Notify the layer above us
1044+ nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
1045+
1046+ InterlockedDecrement(&netDevice->NumOutstandingSends);
1047+ }
1048+ else
1049+ {
1050+ DPRINT_ERR(NETVSC, "Unknown send completion packet type - %d received!!", nvspPacket->Header.MessageType);
1051+ }
1052+
1053+ PutNetDevice(Device);
1054+ DPRINT_EXIT(NETVSC);
1055+}
1056+
1057+
1058+
1059+static int
1060+NetVscOnSend(
1061+ DEVICE_OBJECT *Device,
1062+ NETVSC_PACKET *Packet
1063+ )
1064+{
1065+ NETVSC_DEVICE* netDevice;
1066+ int ret=0;
1067+
1068+ NVSP_MESSAGE sendMessage;
1069+
1070+ DPRINT_ENTER(NETVSC);
1071+
1072+ netDevice = GetOutboundNetDevice(Device);
1073+ if (!netDevice)
1074+ {
1075+ DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring outbound packets", netDevice);
1076+ DPRINT_EXIT(NETVSC);
1077+ return -2;
1078+ }
1079+
1080+ sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
1081+ if (Packet->IsDataPacket)
1082+ sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;// 0 is RMC_DATA;
1083+ else
1084+ sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;// 1 is RMC_CONTROL;
1085+
1086+ // Not using send buffer section
1087+ sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
1088+ sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
1089+
1090+ if (Packet->PageBufferCount)
1091+ {
1092+ ret = Device->Driver->VmbusChannelInterface.SendPacketPageBuffer(Device,
1093+ Packet->PageBuffers,
1094+ Packet->PageBufferCount,
1095+ &sendMessage,
1096+ sizeof(NVSP_MESSAGE),
1097+ (ULONG_PTR)Packet);
1098+ }
1099+ else
1100+ {
1101+ ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1102+ &sendMessage,
1103+ sizeof(NVSP_MESSAGE),
1104+ (ULONG_PTR)Packet,
1105+ VmbusPacketTypeDataInBand,
1106+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1107+
1108+ }
1109+
1110+ if (ret != 0)
1111+ {
1112+ DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d", Packet, ret);
1113+ }
1114+
1115+ InterlockedIncrement(&netDevice->NumOutstandingSends);
1116+ PutNetDevice(Device);
1117+
1118+ DPRINT_EXIT(NETVSC);
1119+ return ret;
1120+}
1121+
1122+
1123+static void
1124+NetVscOnReceive(
1125+ DEVICE_OBJECT *Device,
1126+ VMPACKET_DESCRIPTOR *Packet
1127+ )
1128+{
1129+ NETVSC_DEVICE* netDevice;
1130+ VMTRANSFER_PAGE_PACKET_HEADER *vmxferpagePacket;
1131+ NVSP_MESSAGE *nvspPacket;
1132+ NETVSC_PACKET *netvscPacket=NULL;
1133+ LIST_ENTRY* entry;
1134+ ULONG_PTR start;
1135+ ULONG_PTR end, endVirtual;
1136+ //NETVSC_DRIVER_OBJECT *netvscDriver;
1137+ XFERPAGE_PACKET *xferpagePacket=NULL;
1138+ LIST_ENTRY listHead;
1139+
1140+ int i=0, j=0;
1141+ int count=0, bytesRemain=0;
1142+
1143+ DPRINT_ENTER(NETVSC);
1144+
1145+ netDevice = GetInboundNetDevice(Device);
1146+ if (!netDevice)
1147+ {
1148+ DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1149+ DPRINT_EXIT(NETVSC);
1150+ return;
1151+ }
1152+
1153+ // All inbound packets other than send completion should be xfer page packet
1154+ if (Packet->Type != VmbusPacketTypeDataUsingTransferPages)
1155+ {
1156+ DPRINT_ERR(NETVSC, "Unknown packet type received - %d", Packet->Type);
1157+ PutNetDevice(Device);
1158+ return;
1159+ }
1160+
1161+ nvspPacket = (NVSP_MESSAGE*)((ULONG_PTR)Packet + (Packet->DataOffset8 << 3));
1162+
1163+ // Make sure this is a valid nvsp packet
1164+ if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket )
1165+ {
1166+ DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d", nvspPacket->Header.MessageType);
1167+ PutNetDevice(Device);
1168+ return;
1169+ }
1170+
1171+ DPRINT_DBG(NETVSC, "NVSP packet received - type %d", nvspPacket->Header.MessageType);
1172+
1173+ vmxferpagePacket = (VMTRANSFER_PAGE_PACKET_HEADER*)Packet;
1174+
1175+ if (vmxferpagePacket->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID)
1176+ {
1177+ DPRINT_ERR(NETVSC, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, vmxferpagePacket->TransferPageSetId);
1178+ PutNetDevice(Device);
1179+ return;
1180+ }
1181+
1182+ DPRINT_DBG(NETVSC, "xfer page - range count %d", vmxferpagePacket->RangeCount);
1183+
1184+ INITIALIZE_LIST_HEAD(&listHead);
1185+
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))
1190+ {
1191+ entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
1192+ netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1193+
1194+ INSERT_TAIL_LIST(&listHead, &netvscPacket->ListEntry);
1195+
1196+ if (++count == vmxferpagePacket->RangeCount + 1)
1197+ break;
1198+ }
1199+ SpinlockRelease(netDevice->ReceivePacketListLock);
1200+
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...
1203+ if (count < 2)
1204+ {
1205+ DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count, vmxferpagePacket->RangeCount+1);
1206+
1207+ // Return it to the freelist
1208+ SpinlockAcquire(netDevice->ReceivePacketListLock);
1209+ for (i=count; i != 0; i--)
1210+ {
1211+ entry = REMOVE_HEAD_LIST(&listHead);
1212+ netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1213+
1214+ INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &netvscPacket->ListEntry);
1215+ }
1216+ SpinlockRelease(netDevice->ReceivePacketListLock);
1217+
1218+ NetVscSendReceiveCompletion(Device, vmxferpagePacket->d.TransactionId);
1219+
1220+ PutNetDevice(Device);
1221+ return;
1222+ }
1223+
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);
1229+
1230+ if (xferpagePacket->Count != vmxferpagePacket->RangeCount)
1231+ {
1232+ DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket->RangeCount, xferpagePacket->Count);
1233+ }
1234+
1235+ // Each range represents 1 RNDIS pkt that contains 1 ethernet frame
1236+ for (i=0; i < (count - 1); i++)
1237+ {
1238+ entry = REMOVE_HEAD_LIST(&listHead);
1239+ netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1240+
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
1247+
1248+ netvscPacket->TotalDataBufferLength = vmxferpagePacket->Ranges[i].ByteCount;
1249+ netvscPacket->PageBufferCount = 1;
1250+
1251+ ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + vmxferpagePacket->Ranges[i].ByteCount < netDevice->ReceiveBufferSize);
1252+
1253+ netvscPacket->PageBuffers[0].Length = vmxferpagePacket->Ranges[i].ByteCount;
1254+
1255+ start = GetPhysicalAddress((void*)((ULONG_PTR)netDevice->ReceiveBuffer + vmxferpagePacket->Ranges[i].ByteOffset));
1256+
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);
1262+
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;
1274+ bytesRemain = 0;
1275+ } else {
1276+ netvscPacket->PageBuffers[j].Length = PAGE_SIZE;
1277+ bytesRemain -= PAGE_SIZE;
1278+ }
1279+ netvscPacket->PageBuffers[j].Pfn =
1280+ GetPhysicalAddress((void*)(endVirtual - bytesRemain)) >> PAGE_SHIFT;
1281+ netvscPacket->PageBufferCount++;
1282+ if (bytesRemain == 0)
1283+ break;
1284+ }
1285+ ASSERT(bytesRemain == 0);
1286+ }
1287+ DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1288+ i,
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);
1294+
1295+ // Pass it to the upper layer
1296+ ((NETVSC_DRIVER_OBJECT*)Device->Driver)->OnReceiveCallback(Device, netvscPacket);
1297+
1298+ NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
1299+ }
1300+
1301+ ASSERT(IsListEmpty(&listHead));
1302+
1303+ PutNetDevice(Device);
1304+ DPRINT_EXIT(NETVSC);
1305+}
1306+
1307+
1308+static void
1309+NetVscSendReceiveCompletion(
1310+ DEVICE_OBJECT *Device,
1311+ UINT64 TransactionId
1312+ )
1313+{
1314+ NVSP_MESSAGE recvcompMessage;
1315+ int retries=0;
1316+ int ret=0;
1317+
1318+ DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx", TransactionId);
1319+
1320+ recvcompMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacketComplete;
1321+
1322+ // FIXME: Pass in the status
1323+ recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
1324+
1325+retry_send_cmplt:
1326+ // Send the completion
1327+ ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1328+ &recvcompMessage,
1329+ sizeof(NVSP_MESSAGE),
1330+ TransactionId,
1331+ VmbusPacketTypeCompletion,
1332+ 0);
1333+ if (ret == 0) // success
1334+ {
1335+ // no-op
1336+ }
1337+ else if (ret == -1) // no more room...wait a bit and attempt to retry 3 times
1338+ {
1339+ retries++;
1340+ DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId, retries);
1341+
1342+ if (retries < 4)
1343+ {
1344+ Sleep(100);
1345+ goto retry_send_cmplt;
1346+ }
1347+ else
1348+ {
1349+ DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId);
1350+ }
1351+ }
1352+ else
1353+ {
1354+ DPRINT_ERR(NETVSC, "unable to send receive completion pkt - %llx", TransactionId);
1355+ }
1356+}
1357+
1358+//
1359+// Send a receive completion packet to RNDIS device (ie NetVsp)
1360+//
1361+static void
1362+NetVscOnReceiveCompletion(
1363+ PVOID Context)
1364+{
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;
1370+
1371+ DPRINT_ENTER(NETVSC);
1372+
1373+ ASSERT(packet->XferPagePacket);
1374+
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);
1378+ if (!netDevice)
1379+ {
1380+ DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1381+ DPRINT_EXIT(NETVSC);
1382+ return;
1383+ }
1384+
1385+ // Overloading use of the lock.
1386+ SpinlockAcquire(netDevice->ReceivePacketListLock);
1387+
1388+ ASSERT(packet->XferPagePacket->Count > 0);
1389+ packet->XferPagePacket->Count--;
1390+
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)
1394+ {
1395+ fSendReceiveComp = TRUE;
1396+ transactionId = packet->Completion.Recv.ReceiveCompletionTid;
1397+
1398+ INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->XferPagePacket->ListEntry);
1399+ }
1400+
1401+ // Put the packet back
1402+ INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
1403+ SpinlockRelease(netDevice->ReceivePacketListLock);
1404+
1405+ // Send a receive completion for the xfer page packet
1406+ if (fSendReceiveComp)
1407+ {
1408+ NetVscSendReceiveCompletion(device, transactionId);
1409+ }
1410+
1411+ PutNetDevice(device);
1412+ DPRINT_EXIT(NETVSC);
1413+}
1414+
1415+
1416+
1417+void
1418+NetVscOnChannelCallback(
1419+ PVOID Context
1420+ )
1421+{
1422+ const int netPacketSize=2048;
1423+ int ret=0;
1424+ DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
1425+ NETVSC_DEVICE *netDevice;
1426+
1427+ UINT32 bytesRecvd;
1428+ UINT64 requestId;
1429+ UCHAR packet[netPacketSize];
1430+ VMPACKET_DESCRIPTOR *desc;
1431+ UCHAR *buffer=packet;
1432+ int bufferlen=netPacketSize;
1433+
1434+
1435+ DPRINT_ENTER(NETVSC);
1436+
1437+ ASSERT(device);
1438+
1439+ netDevice = GetInboundNetDevice(device);
1440+ if (!netDevice)
1441+ {
1442+ DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring inbound packets", netDevice);
1443+ DPRINT_EXIT(NETVSC);
1444+ return;
1445+ }
1446+
1447+ do
1448+ {
1449+ ret = device->Driver->VmbusChannelInterface.RecvPacketRaw(device,
1450+ buffer,
1451+ bufferlen,
1452+ &bytesRecvd,
1453+ &requestId);
1454+
1455+ if (ret == 0)
1456+ {
1457+ if (bytesRecvd > 0)
1458+ {
1459+ DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx", bytesRecvd, requestId);
1460+
1461+ desc = (VMPACKET_DESCRIPTOR*)buffer;
1462+ switch (desc->Type)
1463+ {
1464+ case VmbusPacketTypeCompletion:
1465+ NetVscOnSendCompletion(device, desc);
1466+ break;
1467+
1468+ case VmbusPacketTypeDataUsingTransferPages:
1469+ NetVscOnReceive(device, desc);
1470+ break;
1471+
1472+ default:
1473+ DPRINT_ERR(NETVSC, "unhandled packet type %d, tid %llx len %d\n", desc->Type, requestId, bytesRecvd);
1474+ break;
1475+ }
1476+
1477+ // reset
1478+ if (bufferlen > netPacketSize)
1479+ {
1480+ MemFree(buffer);
1481+
1482+ buffer = packet;
1483+ bufferlen = netPacketSize;
1484+ }
1485+ }
1486+ else
1487+ {
1488+ //DPRINT_DBG(NETVSC, "nothing else to read...");
1489+
1490+ // reset
1491+ if (bufferlen > netPacketSize)
1492+ {
1493+ MemFree(buffer);
1494+
1495+ buffer = packet;
1496+ bufferlen = netPacketSize;
1497+ }
1498+
1499+ break;
1500+ }
1501+ }
1502+ else if (ret == -2) // Handle large packet
1503+ {
1504+ buffer = MemAllocAtomic(bytesRecvd);
1505+ if (buffer == NULL)
1506+ {
1507+ // Try again next time around
1508+ DPRINT_ERR(NETVSC, "unable to allocate buffer of size (%d)!!", bytesRecvd);
1509+ break;
1510+ }
1511+
1512+ bufferlen = bytesRecvd;
1513+ }
1514+ else
1515+ {
1516+ ASSERT(0);
1517+ }
1518+ } while (1);
1519+
1520+ PutNetDevice(device);
1521+ DPRINT_EXIT(NETVSC);
1522+ return;
1523+}
1524--- /dev/null
1525+++ b/drivers/staging/hv/netvsc_drv.c
1526@@ -0,0 +1,720 @@
1527+/*
1528+ *
1529+ * Copyright (c) 2009, Microsoft Corporation.
1530+ *
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.
1534+ *
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
1538+ * more details.
1539+ *
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.
1543+ *
1544+ * Authors:
1545+ * Hank Janssen <hjanssen@microsoft.com>
1546+ *
1547+ */
1548+
1549+
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>
1556+#else
1557+#include <linux/io.h>
1558+#endif
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>
1569+
1570+#include "logging.h"
1571+#include "vmbus.h"
1572+
1573+#include "NetVscApi.h"
1574+
1575+MODULE_LICENSE("GPL");
1576+
1577+//
1578+// Static decl
1579+//
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);
1589+
1590+//
1591+// Data types
1592+//
1593+struct net_device_context {
1594+ struct device_context *device_ctx; // point back to our device context
1595+ struct net_device_stats stats;
1596+};
1597+
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;
1602+};
1603+
1604+//
1605+// Globals
1606+//
1607+
1608+static int netvsc_ringbuffer_size = NETVSC_DEVICE_RING_BUFFER_SIZE;
1609+
1610+// The one and only one
1611+static struct netvsc_driver_context g_netvsc_drv;
1612+
1613+//
1614+// Routines
1615+//
1616+
1617+/*++
1618+
1619+Name: netvsc_drv_init()
1620+
1621+Desc: NetVsc driver initialization
1622+
1623+--*/
1624+int netvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
1625+{
1626+ int ret=0;
1627+ NETVSC_DRIVER_OBJECT *net_drv_obj=&g_netvsc_drv.drv_obj;
1628+ struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;
1629+
1630+ DPRINT_ENTER(NETVSC_DRV);
1631+
1632+ vmbus_get_interface(&net_drv_obj->Base.VmbusChannelInterface);
1633+
1634+ net_drv_obj->RingBufferSize = netvsc_ringbuffer_size;
1635+ net_drv_obj->OnReceiveCallback = netvsc_recv_callback;
1636+ net_drv_obj->OnLinkStatusChanged = netvsc_linkstatus_callback;
1637+
1638+ // Callback to client driver to complete the initialization
1639+ pfn_drv_init(&net_drv_obj->Base);
1640+
1641+ drv_ctx->driver.name = net_drv_obj->Base.name;
1642+ memcpy(&drv_ctx->class_id, &net_drv_obj->Base.deviceType, sizeof(GUID));
1643+
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;
1647+#else
1648+ drv_ctx->probe = netvsc_probe;
1649+ drv_ctx->remove = netvsc_remove;
1650+#endif
1651+
1652+ // The driver belongs to vmbus
1653+ vmbus_child_driver_register(drv_ctx);
1654+
1655+ DPRINT_EXIT(NETVSC_DRV);
1656+
1657+ return ret;
1658+}
1659+
1660+/*++
1661+
1662+Name: netvsc_get_stats()
1663+
1664+Desc: Get the network stats
1665+
1666+--*/
1667+static struct net_device_stats *netvsc_get_stats(struct net_device *net)
1668+{
1669+ struct net_device_context *net_device_ctx = netdev_priv(net);
1670+
1671+ return &net_device_ctx->stats;
1672+}
1673+
1674+/*++
1675+
1676+Name: netvsc_set_multicast_list()
1677+
1678+Desc: Set the multicast list
1679+
1680+Remark: No-op here
1681+--*/
1682+static void netvsc_set_multicast_list(UNUSED_VAR(struct net_device *net))
1683+{
1684+}
1685+
1686+
1687+/*++
1688+
1689+Name: netvsc_probe()
1690+
1691+Desc: Add the specified new device to this driver
1692+
1693+--*/
1694+static int netvsc_probe(struct device *device)
1695+{
1696+ int ret=0;
1697+
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;
1701+
1702+ struct device_context *device_ctx = device_to_device_context(device);
1703+ DEVICE_OBJECT *device_obj = &device_ctx->device_obj;
1704+
1705+ struct net_device *net = NULL;
1706+ struct net_device_context *net_device_ctx;
1707+ NETVSC_DEVICE_INFO device_info;
1708+
1709+ DPRINT_ENTER(NETVSC_DRV);
1710+
1711+ if (!net_drv_obj->Base.OnDeviceAdd)
1712+ {
1713+ return -1;
1714+ }
1715+
1716+ net = alloc_netdev(sizeof(struct net_device_context), "seth%d", ether_setup);
1717+ //net = alloc_etherdev(sizeof(struct net_device_context));
1718+ if (!net)
1719+ {
1720+ return -1;
1721+ }
1722+
1723+ // Set initial state
1724+ netif_carrier_off(net);
1725+ netif_stop_queue(net);
1726+
1727+ net_device_ctx = netdev_priv(net);
1728+ net_device_ctx->device_ctx = device_ctx;
1729+ device->driver_data = net;
1730+
1731+ // Notify the netvsc driver of the new device
1732+ ret = net_drv_obj->Base.OnDeviceAdd(device_obj, (void*)&device_info);
1733+ if (ret != 0)
1734+ {
1735+ free_netdev(net);
1736+ device->driver_data = NULL;
1737+
1738+ DPRINT_ERR(NETVSC_DRV, "unable to add netvsc device (ret %d)", ret);
1739+ return ret;
1740+ }
1741+
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))
1745+ {
1746+ if (!device_info.LinkState)
1747+ {
1748+ netif_carrier_on(net);
1749+ }
1750+ }
1751+
1752+ memcpy(net->dev_addr, device_info.MacAddr, ETH_ALEN);
1753+
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;
1759+
1760+#if !defined(KERNEL_2_6_27)
1761+ SET_MODULE_OWNER(net);
1762+#endif
1763+ SET_NETDEV_DEV(net, device);
1764+
1765+ ret = register_netdev(net);
1766+ if (ret != 0)
1767+ {
1768+ // Remove the device and release the resource
1769+ net_drv_obj->Base.OnDeviceRemove(device_obj);
1770+ free_netdev(net);
1771+ }
1772+
1773+ DPRINT_EXIT(NETVSC_DRV);
1774+
1775+ return ret;
1776+}
1777+
1778+static int netvsc_remove(struct device *device)
1779+{
1780+ int ret=0;
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;
1784+
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;
1788+
1789+ DPRINT_ENTER(NETVSC_DRV);
1790+
1791+ if (net == NULL)
1792+ {
1793+ DPRINT_INFO(NETVSC, "no net device to remove");
1794+ DPRINT_EXIT(NETVSC_DRV);
1795+ return 0;
1796+ }
1797+
1798+ if (!net_drv_obj->Base.OnDeviceRemove)
1799+ {
1800+ DPRINT_EXIT(NETVSC_DRV);
1801+ return -1;
1802+ }
1803+
1804+ // Stop outbound asap
1805+ netif_stop_queue(net);
1806+ //netif_carrier_off(net);
1807+
1808+ unregister_netdev(net);
1809+
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);
1812+ if (ret != 0)
1813+ {
1814+ // TODO:
1815+ DPRINT_ERR(NETVSC, "unable to remove vsc device (ret %d)", ret);
1816+ }
1817+
1818+ free_netdev(net);
1819+
1820+ DPRINT_EXIT(NETVSC_DRV);
1821+
1822+ return ret;
1823+}
1824+
1825+/*++
1826+
1827+Name: netvsc_open()
1828+
1829+Desc: Open the specified interface device
1830+
1831+--*/
1832+static int netvsc_open(struct net_device *net)
1833+{
1834+ int ret=0;
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;
1839+
1840+ DEVICE_OBJECT *device_obj = &net_device_ctx->device_ctx->device_obj;
1841+
1842+ DPRINT_ENTER(NETVSC_DRV);
1843+
1844+ if (netif_carrier_ok(net))
1845+ {
1846+ memset(&net_device_ctx->stats, 0 , sizeof(struct net_device_stats));
1847+
1848+ // Open up the device
1849+ ret = net_drv_obj->OnOpen(device_obj);
1850+ if (ret != 0)
1851+ {
1852+ DPRINT_ERR(NETVSC_DRV, "unable to open device (ret %d).", ret);
1853+ return ret;
1854+ }
1855+
1856+ netif_start_queue(net);
1857+ }
1858+ else
1859+ {
1860+ DPRINT_ERR(NETVSC_DRV, "unable to open device...link is down.");
1861+ }
1862+
1863+ DPRINT_EXIT(NETVSC_DRV);
1864+ return ret;
1865+}
1866+
1867+/*++
1868+
1869+Name: netvsc_close()
1870+
1871+Desc: Close the specified interface device
1872+
1873+--*/
1874+static int netvsc_close(struct net_device *net)
1875+{
1876+ int ret=0;
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;
1881+
1882+ DEVICE_OBJECT *device_obj = &net_device_ctx->device_ctx->device_obj;
1883+
1884+ DPRINT_ENTER(NETVSC_DRV);
1885+
1886+ netif_stop_queue(net);
1887+
1888+ ret = net_drv_obj->OnClose(device_obj);
1889+ if (ret != 0)
1890+ {
1891+ DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);
1892+ }
1893+
1894+ DPRINT_EXIT(NETVSC_DRV);
1895+
1896+ return ret;
1897+}
1898+
1899+
1900+/*++
1901+
1902+Name: netvsc_xmit_completion()
1903+
1904+Desc: Send completion processing
1905+
1906+--*/
1907+static void netvsc_xmit_completion(void *context)
1908+{
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;
1912+
1913+ DPRINT_ENTER(NETVSC_DRV);
1914+
1915+ kfree(packet);
1916+
1917+ if (skb)
1918+ {
1919+ net = skb->dev;
1920+
1921+ dev_kfree_skb_any(skb);
1922+
1923+ if (netif_queue_stopped(net))
1924+ {
1925+ DPRINT_INFO(NETVSC_DRV, "net device (%p) waking up...", net);
1926+
1927+ netif_wake_queue(net);
1928+ }
1929+ }
1930+
1931+ DPRINT_EXIT(NETVSC_DRV);
1932+}
1933+
1934+/*++
1935+
1936+Name: netvsc_start_xmit()
1937+
1938+Desc: Start a send
1939+
1940+--*/
1941+static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
1942+{
1943+ int ret=0;
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;
1948+
1949+ int i=0;
1950+ NETVSC_PACKET* packet;
1951+ int num_frags;
1952+ int retries=0;
1953+
1954+ DPRINT_ENTER(NETVSC_DRV);
1955+
1956+ // Support only 1 chain of frags
1957+ ASSERT(skb_shinfo(skb)->frag_list == NULL);
1958+ ASSERT(skb->dev == net);
1959+
1960+ DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d", skb->len, skb->data_len);
1961+
1962+ // Add 1 for skb->data and any additional ones requested
1963+ num_frags = skb_shinfo(skb)->nr_frags + 1 + net_drv_obj->AdditionalRequestPageBufferCount;
1964+
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);
1967+ if (!packet)
1968+ {
1969+ DPRINT_ERR(NETVSC_DRV, "unable to allocate NETVSC_PACKET");
1970+ return -1;
1971+ }
1972+
1973+ packet->Extension = (void*)(unsigned long)packet + sizeof(NETVSC_PACKET) + (num_frags * sizeof(PAGE_BUFFER)) ;
1974+
1975+ // Setup the rndis header
1976+ packet->PageBufferCount = num_frags;
1977+
1978+ // TODO: Flush all write buffers/ memory fence ???
1979+ //wmb();
1980+
1981+ // Initialize it from the skb
1982+ ASSERT(skb->data);
1983+ packet->TotalDataBufferLength = skb->len;
1984+
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;
1989+
1990+ ASSERT((skb->len - skb->data_len) <= PAGE_SIZE);
1991+
1992+ for (i=net_drv_obj->AdditionalRequestPageBufferCount+1; i<num_frags; i++)
1993+ {
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;
1997+ }
1998+
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;
2003+
2004+retry_send:
2005+ ret = net_drv_obj->OnSend(&net_device_ctx->device_ctx->device_obj, packet);
2006+
2007+ if (ret == 0)
2008+ {
2009+#ifdef KERNEL_2_6_5
2010+#define NETDEV_TX_OK 0
2011+#define NETDEV_TX_BUSY 0
2012+#endif
2013+ ret = NETDEV_TX_OK;
2014+ net_device_ctx->stats.tx_bytes += skb->len;
2015+ net_device_ctx->stats.tx_packets++;
2016+ }
2017+ else
2018+ {
2019+ retries++;
2020+ if (retries < 4)
2021+ {
2022+ DPRINT_ERR(NETVSC_DRV, "unable to send...retrying %d...", retries);
2023+ udelay(100);
2024+ goto retry_send;
2025+ }
2026+
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);
2030+
2031+ ret = NETDEV_TX_BUSY;
2032+ net_device_ctx->stats.tx_dropped++;
2033+
2034+ netif_stop_queue(net);
2035+
2036+ // Null it since the caller will free it instead of the completion routine
2037+ packet->Completion.Send.SendCompletionTid = 0;
2038+
2039+ // Release the resources since we will not get any send completion
2040+ netvsc_xmit_completion((void*)packet);
2041+ }
2042+
2043+ DPRINT_DBG(NETVSC_DRV, "# of xmits %lu total size %lu", net_device_ctx->stats.tx_packets, net_device_ctx->stats.tx_bytes);
2044+
2045+ DPRINT_EXIT(NETVSC_DRV);
2046+ return ret;
2047+}
2048+
2049+
2050+/*++
2051+
2052+Name: netvsc_linkstatus_callback()
2053+
2054+Desc: Link up/down notification
2055+
2056+--*/
2057+static void netvsc_linkstatus_callback(DEVICE_OBJECT *device_obj, unsigned int status)
2058+{
2059+ struct device_context* device_ctx = to_device_context(device_obj);
2060+ struct net_device* net = (struct net_device *)device_ctx->device.driver_data;
2061+
2062+ DPRINT_ENTER(NETVSC_DRV);
2063+
2064+ if (!net)
2065+ {
2066+ DPRINT_ERR(NETVSC_DRV, "got link status but net device not initialized yet");
2067+ return;
2068+ }
2069+
2070+ if (status == 1)
2071+ {
2072+ netif_carrier_on(net);
2073+ netif_wake_queue(net);
2074+ }
2075+ else
2076+ {
2077+ netif_carrier_off(net);
2078+ netif_stop_queue(net);
2079+ }
2080+ DPRINT_EXIT(NETVSC_DRV);
2081+}
2082+
2083+
2084+/*++
2085+
2086+Name: netvsc_recv_callback()
2087+
2088+Desc: Callback when we receive a packet from the "wire" on the specify device
2089+
2090+--*/
2091+static int netvsc_recv_callback(DEVICE_OBJECT *device_obj, NETVSC_PACKET* packet)
2092+{
2093+ int ret=0;
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;
2097+
2098+ struct sk_buff *skb;
2099+ void *data;
2100+ int i=0;
2101+ unsigned long flags;
2102+
2103+ DPRINT_ENTER(NETVSC_DRV);
2104+
2105+ if (!net)
2106+ {
2107+ DPRINT_ERR(NETVSC_DRV, "got receive callback but net device not initialized yet");
2108+ return 0;
2109+ }
2110+
2111+ net_device_ctx = netdev_priv(net);
2112+
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
2116+ ASSERT(skb);
2117+ skb_reserve(skb, 2);
2118+ skb->dev = net;
2119+
2120+ // for kmap_atomic
2121+ local_irq_save(flags);
2122+
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++)
2126+ {
2127+ data = kmap_atomic(pfn_to_page(packet->PageBuffers[i].Pfn), KM_IRQ1);
2128+ data = (void*)(unsigned long)data + packet->PageBuffers[i].Offset;
2129+
2130+ memcpy(skb_put(skb, packet->PageBuffers[i].Length), data, packet->PageBuffers[i].Length);
2131+
2132+ kunmap_atomic((void*)((unsigned long)data - packet->PageBuffers[i].Offset), KM_IRQ1);
2133+ }
2134+
2135+ local_irq_restore(flags);
2136+
2137+ skb->protocol = eth_type_trans(skb, net);
2138+
2139+ skb->ip_summed = CHECKSUM_NONE;
2140+
2141+ // Pass the skb back up. Network stack will deallocate the skb when it is done
2142+ ret = netif_rx(skb);
2143+
2144+ switch (ret)
2145+ {
2146+ case NET_RX_DROP:
2147+ net_device_ctx->stats.rx_dropped++;
2148+ break;
2149+ default:
2150+ net_device_ctx->stats.rx_packets++;
2151+ net_device_ctx->stats.rx_bytes += skb->len;
2152+ break;
2153+
2154+ }
2155+ DPRINT_DBG(NETVSC_DRV, "# of recvs %lu total size %lu", net_device_ctx->stats.rx_packets, net_device_ctx->stats.rx_bytes);
2156+
2157+ DPRINT_EXIT(NETVSC_DRV);
2158+
2159+ return 0;
2160+}
2161+
2162+static int netvsc_drv_exit_cb(struct device *dev, void *data)
2163+{
2164+ struct device **curr = (struct device **)data;
2165+ *curr = dev;
2166+ return 1; // stop iterating
2167+}
2168+
2169+/*++
2170+
2171+Name: netvsc_drv_exit()
2172+
2173+Desc:
2174+
2175+--*/
2176+void netvsc_drv_exit(void)
2177+{
2178+ NETVSC_DRIVER_OBJECT *netvsc_drv_obj=&g_netvsc_drv.drv_obj;
2179+ struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;
2180+
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);\
2189+ }
2190+#endif
2191+
2192+ DPRINT_ENTER(NETVSC_DRV);
2193+
2194+ while (1)
2195+ {
2196+ current_dev = NULL;
2197+
2198+ // Get the device
2199+ driver_for_each_device(&drv_ctx->driver, NULL, (void*)&current_dev, netvsc_drv_exit_cb);
2200+
2201+ if (current_dev == NULL)
2202+ break;
2203+
2204+ // Initiate removal from the top-down
2205+ DPRINT_INFO(NETVSC_DRV, "unregistering device (%p)...", current_dev);
2206+
2207+ device_unregister(current_dev);
2208+ }
2209+
2210+ if (netvsc_drv_obj->Base.OnCleanup)
2211+ netvsc_drv_obj->Base.OnCleanup(&netvsc_drv_obj->Base);
2212+
2213+ vmbus_child_driver_unregister(drv_ctx);
2214+
2215+ DPRINT_EXIT(NETVSC_DRV);
2216+
2217+ return;
2218+}
2219+
2220+static int __init netvsc_init(void)
2221+{
2222+ int ret;
2223+
2224+ DPRINT_ENTER(NETVSC_DRV);
2225+ DPRINT_INFO(NETVSC_DRV, "Netvsc initializing....");
2226+
2227+ ret = netvsc_drv_init(NetVscInitialize);
2228+
2229+ DPRINT_EXIT(NETVSC_DRV);
2230+
2231+ return ret;
2232+}
2233+
2234+static void __exit netvsc_exit(void)
2235+{
2236+ DPRINT_ENTER(NETVSC_DRV);
2237+
2238+ netvsc_drv_exit();
2239+
2240+ DPRINT_EXIT(NETVSC_DRV);
2241+}
2242+
2243+module_param(netvsc_ringbuffer_size, int, S_IRUGO);
2244+
2245+module_init(netvsc_init);
2246+module_exit(netvsc_exit);
2247--- /dev/null
2248+++ b/drivers/staging/hv/NetVsc.h
2249@@ -0,0 +1,91 @@
2250+/*
2251+ *
2252+ * Copyright (c) 2009, Microsoft Corporation.
2253+ *
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.
2257+ *
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
2261+ * more details.
2262+ *
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.
2266+ *
2267+ * Authors:
2268+ * Hank Janssen <hjanssen@microsoft.com>
2269+ *
2270+ */
2271+
2272+
2273+#ifndef _NETVSC_H_
2274+#define _NETVSC_H_
2275+
2276+#include "VmbusPacketFormat.h"
2277+#include "nvspprotocol.h"
2278+
2279+#include "List.h"
2280+
2281+#include "NetVscApi.h"
2282+//
2283+// #defines
2284+//
2285+//#define NVSC_MIN_PROTOCOL_VERSION 1
2286+//#define NVSC_MAX_PROTOCOL_VERSION 1
2287+
2288+#define NETVSC_SEND_BUFFER_SIZE 64*1024 // 64K
2289+#define NETVSC_SEND_BUFFER_ID 0xface
2290+
2291+
2292+#define NETVSC_RECEIVE_BUFFER_SIZE 1024*1024 // 1MB
2293+
2294+#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
2295+
2296+#define NETVSC_RECEIVE_SG_COUNT 1
2297+
2298+// Preallocated receive packets
2299+#define NETVSC_RECEIVE_PACKETLIST_COUNT 256
2300+
2301+//
2302+// Data types
2303+//
2304+
2305+// Per netvsc channel-specific
2306+typedef struct _NETVSC_DEVICE {
2307+ DEVICE_OBJECT *Device;
2308+
2309+ int RefCount;
2310+
2311+ int NumOutstandingSends;
2312+ // List of free preallocated NETVSC_PACKET to represent receive packet
2313+ LIST_ENTRY ReceivePacketList;
2314+ HANDLE ReceivePacketListLock;
2315+
2316+ // Send buffer allocated by us but manages by NetVSP
2317+ PVOID SendBuffer;
2318+ UINT32 SendBufferSize;
2319+ UINT32 SendBufferGpadlHandle;
2320+ UINT32 SendSectionSize;
2321+
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;
2328+
2329+ // Used for NetVSP initialization protocol
2330+ HANDLE ChannelInitEvent;
2331+ NVSP_MESSAGE ChannelInitPacket;
2332+
2333+ NVSP_MESSAGE RevokePacket;
2334+ //UCHAR HwMacAddr[HW_MACADDR_LEN];
2335+
2336+ // Holds rndis device info
2337+ void *Extension;
2338+} NETVSC_DEVICE;
2339+
2340+#endif // _NETVSC_H_
2341--- /dev/null
2342+++ b/drivers/staging/hv/RndisFilter.c
2343@@ -0,0 +1,1162 @@
2344+/*
2345+ *
2346+ * Copyright (c) 2009, Microsoft Corporation.
2347+ *
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.
2351+ *
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
2355+ * more details.
2356+ *
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.
2360+ *
2361+ * Authors:
2362+ * Haiyang Zhang <haiyangz@microsoft.com>
2363+ * Hank Janssen <hjanssen@microsoft.com>
2364+ *
2365+ */
2366+
2367+
2368+#include "logging.h"
2369+
2370+#include "NetVscApi.h"
2371+#include "RndisFilter.h"
2372+
2373+//
2374+// Data types
2375+//
2376+
2377+typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
2378+ // The original driver
2379+ NETVSC_DRIVER_OBJECT InnerDriver;
2380+
2381+} RNDIS_FILTER_DRIVER_OBJECT;
2382+
2383+typedef enum {
2384+ RNDIS_DEV_UNINITIALIZED = 0,
2385+ RNDIS_DEV_INITIALIZING,
2386+ RNDIS_DEV_INITIALIZED,
2387+ RNDIS_DEV_DATAINITIALIZED,
2388+} RNDIS_DEVICE_STATE;
2389+
2390+typedef struct _RNDIS_DEVICE {
2391+ NETVSC_DEVICE *NetDevice;
2392+
2393+ RNDIS_DEVICE_STATE State;
2394+ UINT32 LinkStatus;
2395+ UINT32 NewRequestId;
2396+
2397+ HANDLE RequestLock;
2398+ LIST_ENTRY RequestList;
2399+
2400+ UCHAR HwMacAddr[HW_MACADDR_LEN];
2401+} RNDIS_DEVICE;
2402+
2403+
2404+typedef struct _RNDIS_REQUEST {
2405+ LIST_ENTRY ListEntry;
2406+ HANDLE WaitEvent;
2407+
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;
2411+
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;
2417+} RNDIS_REQUEST;
2418+
2419+
2420+typedef struct _RNDIS_FILTER_PACKET {
2421+ void *CompletionContext;
2422+ PFN_ON_SENDRECVCOMPLETION OnCompletion;
2423+
2424+ RNDIS_MESSAGE Message;
2425+} RNDIS_FILTER_PACKET;
2426+
2427+//
2428+// Internal routines
2429+//
2430+static int
2431+RndisFilterSendRequest(
2432+ RNDIS_DEVICE *Device,
2433+ RNDIS_REQUEST *Request
2434+ );
2435+
2436+static void
2437+RndisFilterReceiveResponse(
2438+ RNDIS_DEVICE *Device,
2439+ RNDIS_MESSAGE *Response
2440+ );
2441+
2442+static void
2443+RndisFilterReceiveIndicateStatus(
2444+ RNDIS_DEVICE *Device,
2445+ RNDIS_MESSAGE *Response
2446+ );
2447+
2448+static void
2449+RndisFilterReceiveData(
2450+ RNDIS_DEVICE *Device,
2451+ RNDIS_MESSAGE *Message,
2452+ NETVSC_PACKET *Packet
2453+ );
2454+
2455+static int
2456+RndisFilterOnReceive(
2457+ DEVICE_OBJECT *Device,
2458+ NETVSC_PACKET *Packet
2459+ );
2460+
2461+static int
2462+RndisFilterQueryDevice(
2463+ RNDIS_DEVICE *Device,
2464+ UINT32 Oid,
2465+ VOID *Result,
2466+ UINT32 *ResultSize
2467+ );
2468+
2469+static inline int
2470+RndisFilterQueryDeviceMac(
2471+ RNDIS_DEVICE *Device
2472+ );
2473+
2474+static inline int
2475+RndisFilterQueryDeviceLinkStatus(
2476+ RNDIS_DEVICE *Device
2477+ );
2478+
2479+static int
2480+RndisFilterSetPacketFilter(
2481+ RNDIS_DEVICE *Device,
2482+ UINT32 NewFilter
2483+ );
2484+
2485+static int
2486+RndisFilterInitDevice(
2487+ RNDIS_DEVICE *Device
2488+ );
2489+
2490+static int
2491+RndisFilterOpenDevice(
2492+ RNDIS_DEVICE *Device
2493+ );
2494+
2495+static int
2496+RndisFilterCloseDevice(
2497+ RNDIS_DEVICE *Device
2498+ );
2499+
2500+static int
2501+RndisFilterOnDeviceAdd(
2502+ DEVICE_OBJECT *Device,
2503+ void *AdditionalInfo
2504+ );
2505+
2506+static int
2507+RndisFilterOnDeviceRemove(
2508+ DEVICE_OBJECT *Device
2509+ );
2510+
2511+static void
2512+RndisFilterOnCleanup(
2513+ DRIVER_OBJECT *Driver
2514+ );
2515+
2516+static int
2517+RndisFilterOnOpen(
2518+ DEVICE_OBJECT *Device
2519+ );
2520+
2521+static int
2522+RndisFilterOnClose(
2523+ DEVICE_OBJECT *Device
2524+ );
2525+
2526+static int
2527+RndisFilterOnSend(
2528+ DEVICE_OBJECT *Device,
2529+ NETVSC_PACKET *Packet
2530+ );
2531+
2532+static void
2533+RndisFilterOnSendCompletion(
2534+ void *Context
2535+ );
2536+
2537+static void
2538+RndisFilterOnSendRequestCompletion(
2539+ void *Context
2540+ );
2541+
2542+//
2543+// Global var
2544+//
2545+
2546+// The one and only
2547+RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
2548+
2549+static inline RNDIS_DEVICE* GetRndisDevice(void)
2550+{
2551+ RNDIS_DEVICE *device;
2552+
2553+ device = MemAllocZeroed(sizeof(RNDIS_DEVICE));
2554+ if (!device)
2555+ {
2556+ return NULL;
2557+ }
2558+
2559+ device->RequestLock = SpinlockCreate();
2560+ if (!device->RequestLock)
2561+ {
2562+ MemFree(device);
2563+ return NULL;
2564+ }
2565+
2566+ INITIALIZE_LIST_HEAD(&device->RequestList);
2567+
2568+ device->State = RNDIS_DEV_UNINITIALIZED;
2569+
2570+ return device;
2571+}
2572+
2573+static inline void PutRndisDevice(RNDIS_DEVICE *Device)
2574+{
2575+ SpinlockClose(Device->RequestLock);
2576+ MemFree(Device);
2577+}
2578+
2579+static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, UINT32 MessageType, UINT32 MessageLength)
2580+{
2581+ RNDIS_REQUEST *request;
2582+ RNDIS_MESSAGE *rndisMessage;
2583+ RNDIS_SET_REQUEST *set;
2584+
2585+ request = MemAllocZeroed(sizeof(RNDIS_REQUEST));
2586+ if (!request)
2587+ {
2588+ return NULL;
2589+ }
2590+
2591+ request->WaitEvent = WaitEventCreate();
2592+ if (!request->WaitEvent)
2593+ {
2594+ MemFree(request);
2595+ return NULL;
2596+ }
2597+
2598+ rndisMessage = &request->RequestMessage;
2599+ rndisMessage->NdisMessageType = MessageType;
2600+ rndisMessage->MessageLength = MessageLength;
2601+
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);
2606+
2607+ // Add to the request list
2608+ SpinlockAcquire(Device->RequestLock);
2609+ INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
2610+ SpinlockRelease(Device->RequestLock);
2611+
2612+ return request;
2613+}
2614+
2615+static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
2616+{
2617+ SpinlockAcquire(Device->RequestLock);
2618+ REMOVE_ENTRY_LIST(&Request->ListEntry);
2619+ SpinlockRelease(Device->RequestLock);
2620+
2621+ WaitEventClose(Request->WaitEvent);
2622+ MemFree(Request);
2623+}
2624+
2625+static inline void DumpRndisMessage(RNDIS_MESSAGE *RndisMessage)
2626+{
2627+ switch (RndisMessage->NdisMessageType)
2628+ {
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);
2639+ break;
2640+
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);
2652+ break;
2653+
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);
2661+ break;
2662+
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);
2668+ break;
2669+
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);
2676+ break;
2677+
2678+ default:
2679+ DPRINT_DBG(NETVSC, "0x%x (len %u)",
2680+ RndisMessage->NdisMessageType,
2681+ RndisMessage->MessageLength);
2682+ break;
2683+ }
2684+}
2685+
2686+static int
2687+RndisFilterSendRequest(
2688+ RNDIS_DEVICE *Device,
2689+ RNDIS_REQUEST *Request
2690+ )
2691+{
2692+ int ret=0;
2693+ NETVSC_PACKET *packet;
2694+
2695+ DPRINT_ENTER(NETVSC);
2696+
2697+ // Setup the packet to send it
2698+ packet = &Request->Packet;
2699+
2700+ packet->IsDataPacket = FALSE;
2701+ packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
2702+ packet->PageBufferCount = 1;
2703+
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);
2707+
2708+ packet->Completion.Send.SendCompletionContext = Request;//packet;
2709+ packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
2710+ packet->Completion.Send.SendCompletionTid = (ULONG_PTR)Device;
2711+
2712+ ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
2713+ DPRINT_EXIT(NETVSC);
2714+ return ret;
2715+}
2716+
2717+
2718+static void
2719+RndisFilterReceiveResponse(
2720+ RNDIS_DEVICE *Device,
2721+ RNDIS_MESSAGE *Response
2722+ )
2723+{
2724+ LIST_ENTRY *anchor;
2725+ LIST_ENTRY *curr;
2726+ RNDIS_REQUEST *request=NULL;
2727+ BOOL found=FALSE;
2728+
2729+ DPRINT_ENTER(NETVSC);
2730+
2731+ SpinlockAcquire(Device->RequestLock);
2732+ ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList)
2733+ {
2734+ request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
2735+
2736+ // All request/response message contains RequestId as the 1st field
2737+ if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
2738+ {
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);
2741+
2742+ found = TRUE;
2743+ break;
2744+ }
2745+ }
2746+ SpinlockRelease(Device->RequestLock);
2747+
2748+ if (found)
2749+ {
2750+ if (Response->MessageLength <= sizeof(RNDIS_MESSAGE))
2751+ {
2752+ memcpy(&request->ResponseMessage, Response, Response->MessageLength);
2753+ }
2754+ else
2755+ {
2756+ DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %u)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
2757+
2758+ if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) // does not have a request id field
2759+ {
2760+ request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
2761+ }
2762+ else
2763+ {
2764+ request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
2765+ }
2766+ }
2767+
2768+ WaitEventSet(request->WaitEvent);
2769+ }
2770+ else
2771+ {
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);
2774+ }
2775+
2776+ DPRINT_EXIT(NETVSC);
2777+}
2778+
2779+static void
2780+RndisFilterReceiveIndicateStatus(
2781+ RNDIS_DEVICE *Device,
2782+ RNDIS_MESSAGE *Response
2783+ )
2784+{
2785+ RNDIS_INDICATE_STATUS *indicate = &Response->Message.IndicateStatus;
2786+
2787+ if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT)
2788+ {
2789+ gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
2790+ }
2791+ else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT)
2792+ {
2793+ gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
2794+ }
2795+ else
2796+ {
2797+ // TODO:
2798+ }
2799+}
2800+
2801+static void
2802+RndisFilterReceiveData(
2803+ RNDIS_DEVICE *Device,
2804+ RNDIS_MESSAGE *Message,
2805+ NETVSC_PACKET *Packet
2806+ )
2807+{
2808+ RNDIS_PACKET *rndisPacket;
2809+ UINT32 dataOffset;
2810+
2811+ DPRINT_ENTER(NETVSC);
2812+
2813+ // empty ethernet frame ??
2814+ ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(RNDIS_PACKET));
2815+
2816+ rndisPacket = &Message->Message.Packet;
2817+
2818+ // FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
2819+ // netvsc packet (ie TotalDataBufferLength != MessageLength)
2820+
2821+ // Remove the rndis header and pass it back up the stack
2822+ dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
2823+
2824+ Packet->TotalDataBufferLength -= dataOffset;
2825+ Packet->PageBuffers[0].Offset += dataOffset;
2826+ Packet->PageBuffers[0].Length -= dataOffset;
2827+
2828+ Packet->IsDataPacket = TRUE;
2829+
2830+ gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device, Packet);
2831+
2832+ DPRINT_EXIT(NETVSC);
2833+}
2834+
2835+static int
2836+RndisFilterOnReceive(
2837+ DEVICE_OBJECT *Device,
2838+ NETVSC_PACKET *Packet
2839+ )
2840+{
2841+ NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
2842+ RNDIS_DEVICE *rndisDevice;
2843+ RNDIS_MESSAGE rndisMessage;
2844+ RNDIS_MESSAGE *rndisHeader;
2845+
2846+ DPRINT_ENTER(NETVSC);
2847+
2848+ ASSERT(netDevice);
2849+ //Make sure the rndis device state is initialized
2850+ if (!netDevice->Extension)
2851+ {
2852+ DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
2853+ DPRINT_EXIT(NETVSC);
2854+ return -1;
2855+ }
2856+
2857+ rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
2858+ if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED)
2859+ {
2860+ DPRINT_ERR(NETVSC, "got rndis message but rndis device uninitialized...dropping this message!");
2861+ DPRINT_EXIT(NETVSC);
2862+ return -1;
2863+ }
2864+
2865+ rndisHeader = (RNDIS_MESSAGE*)PageMapVirtualAddress(Packet->PageBuffers[0].Pfn);
2866+
2867+ rndisHeader = (void*)((ULONG_PTR)rndisHeader + Packet->PageBuffers[0].Offset);
2868+
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
2872+#if 0
2873+ if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
2874+ {
2875+ PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
2876+
2877+ DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
2878+ rndisHeader->MessageLength, Packet->TotalDataBufferLength);
2879+ DPRINT_EXIT(NETVSC);
2880+ return -1;
2881+ }
2882+#endif
2883+
2884+ if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE)))
2885+ {
2886+ DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %u)...marking it an error!",
2887+ rndisHeader->MessageLength, sizeof(RNDIS_MESSAGE));
2888+ }
2889+
2890+ memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE))?sizeof(RNDIS_MESSAGE):rndisHeader->MessageLength);
2891+
2892+ PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
2893+
2894+ DumpRndisMessage(&rndisMessage);
2895+
2896+ switch (rndisMessage.NdisMessageType)
2897+ {
2898+ // data msg
2899+ case REMOTE_NDIS_PACKET_MSG:
2900+ RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
2901+ break;
2902+
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);
2910+ break;
2911+
2912+ // notification msgs
2913+ case REMOTE_NDIS_INDICATE_STATUS_MSG:
2914+ RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
2915+ break;
2916+ default:
2917+ DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", rndisMessage.NdisMessageType, rndisMessage.MessageLength);
2918+ break;
2919+ }
2920+
2921+ DPRINT_EXIT(NETVSC);
2922+ return 0;
2923+}
2924+
2925+
2926+static int
2927+RndisFilterQueryDevice(
2928+ RNDIS_DEVICE *Device,
2929+ UINT32 Oid,
2930+ VOID *Result,
2931+ UINT32 *ResultSize
2932+ )
2933+{
2934+ RNDIS_REQUEST *request;
2935+ UINT32 inresultSize = *ResultSize;
2936+ RNDIS_QUERY_REQUEST *query;
2937+ RNDIS_QUERY_COMPLETE *queryComplete;
2938+ int ret=0;
2939+
2940+ DPRINT_ENTER(NETVSC);
2941+
2942+ ASSERT(Result);
2943+
2944+ *ResultSize = 0;
2945+ request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST));
2946+ if (!request)
2947+ {
2948+ ret = -1;
2949+ goto Cleanup;
2950+ }
2951+
2952+ // Setup the rndis query
2953+ query = &request->RequestMessage.Message.QueryRequest;
2954+ query->Oid = Oid;
2955+ query->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
2956+ query->InformationBufferLength = 0;
2957+ query->DeviceVcHandle = 0;
2958+
2959+ ret = RndisFilterSendRequest(Device, request);
2960+ if (ret != 0)
2961+ {
2962+ goto Cleanup;
2963+ }
2964+
2965+ WaitEventWait(request->WaitEvent);
2966+
2967+ // Copy the response back
2968+ queryComplete = &request->ResponseMessage.Message.QueryComplete;
2969+
2970+ if (queryComplete->InformationBufferLength > inresultSize)
2971+ {
2972+ ret = -1;
2973+ goto Cleanup;
2974+ }
2975+
2976+ memcpy(Result,
2977+ (void*)((ULONG_PTR)queryComplete + queryComplete->InformationBufferOffset),
2978+ queryComplete->InformationBufferLength);
2979+
2980+ *ResultSize = queryComplete->InformationBufferLength;
2981+
2982+Cleanup:
2983+ if (request)
2984+ {
2985+ PutRndisRequest(Device, request);
2986+ }
2987+ DPRINT_EXIT(NETVSC);
2988+
2989+ return ret;
2990+}
2991+
2992+static inline int
2993+RndisFilterQueryDeviceMac(
2994+ RNDIS_DEVICE *Device
2995+ )
2996+{
2997+ UINT32 size=HW_MACADDR_LEN;
2998+
2999+ return RndisFilterQueryDevice(Device,
3000+ RNDIS_OID_802_3_PERMANENT_ADDRESS,
3001+ Device->HwMacAddr,
3002+ &size);
3003+}
3004+
3005+static inline int
3006+RndisFilterQueryDeviceLinkStatus(
3007+ RNDIS_DEVICE *Device
3008+ )
3009+{
3010+ UINT32 size=sizeof(UINT32);
3011+
3012+ return RndisFilterQueryDevice(Device,
3013+ RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
3014+ &Device->LinkStatus,
3015+ &size);
3016+}
3017+
3018+static int
3019+RndisFilterSetPacketFilter(
3020+ RNDIS_DEVICE *Device,
3021+ UINT32 NewFilter
3022+ )
3023+{
3024+ RNDIS_REQUEST *request;
3025+ RNDIS_SET_REQUEST *set;
3026+ RNDIS_SET_COMPLETE *setComplete;
3027+ UINT32 status;
3028+ int ret;
3029+
3030+ DPRINT_ENTER(NETVSC);
3031+
3032+ ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(UINT32) <= sizeof(RNDIS_MESSAGE));
3033+
3034+ request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(UINT32));
3035+ if (!request)
3036+ {
3037+ ret = -1;
3038+ goto Cleanup;
3039+ }
3040+
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);
3046+
3047+ memcpy((void*)(ULONG_PTR)set + sizeof(RNDIS_SET_REQUEST), &NewFilter, sizeof(UINT32));
3048+
3049+ ret = RndisFilterSendRequest(Device, request);
3050+ if (ret != 0)
3051+ {
3052+ goto Cleanup;
3053+ }
3054+
3055+ ret = WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
3056+ if (!ret)
3057+ {
3058+ ret = -1;
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.
3061+ goto Exit;
3062+ }
3063+ else
3064+ {
3065+ if (ret > 0)
3066+ {
3067+ ret = 0;
3068+ }
3069+ setComplete = &request->ResponseMessage.Message.SetComplete;
3070+ status = setComplete->Status;
3071+ }
3072+
3073+Cleanup:
3074+ if (request)
3075+ {
3076+ PutRndisRequest(Device, request);
3077+ }
3078+Exit:
3079+ DPRINT_EXIT(NETVSC);
3080+
3081+ return ret;
3082+}
3083+
3084+int
3085+RndisFilterInit(
3086+ NETVSC_DRIVER_OBJECT *Driver
3087+ )
3088+{
3089+ DPRINT_ENTER(NETVSC);
3090+
3091+ DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET));
3092+
3093+ Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
3094+ Driver->AdditionalRequestPageBufferCount = 1; // For rndis header
3095+
3096+ //Driver->Context = rndisDriver;
3097+
3098+ memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
3099+
3100+ /*rndisDriver->Driver = Driver;
3101+
3102+ ASSERT(Driver->OnLinkStatusChanged);
3103+ rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
3104+
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;
3109+
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;
3115+
3116+ // Override
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;
3125+
3126+ DPRINT_EXIT(NETVSC);
3127+
3128+ return 0;
3129+}
3130+
3131+static int
3132+RndisFilterInitDevice(
3133+ RNDIS_DEVICE *Device
3134+ )
3135+{
3136+ RNDIS_REQUEST *request;
3137+ RNDIS_INITIALIZE_REQUEST *init;
3138+ RNDIS_INITIALIZE_COMPLETE *initComplete;
3139+ UINT32 status;
3140+ int ret;
3141+
3142+ DPRINT_ENTER(NETVSC);
3143+
3144+ request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST));
3145+ if (!request)
3146+ {
3147+ ret = -1;
3148+ goto Cleanup;
3149+ }
3150+
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
3156+
3157+ Device->State = RNDIS_DEV_INITIALIZING;
3158+
3159+ ret = RndisFilterSendRequest(Device, request);
3160+ if (ret != 0)
3161+ {
3162+ Device->State = RNDIS_DEV_UNINITIALIZED;
3163+ goto Cleanup;
3164+ }
3165+
3166+ WaitEventWait(request->WaitEvent);
3167+
3168+ initComplete = &request->ResponseMessage.Message.InitializeComplete;
3169+ status = initComplete->Status;
3170+ if (status == RNDIS_STATUS_SUCCESS)
3171+ {
3172+ Device->State = RNDIS_DEV_INITIALIZED;
3173+ ret = 0;
3174+ }
3175+ else
3176+ {
3177+ Device->State = RNDIS_DEV_UNINITIALIZED;
3178+ ret = -1;
3179+ }
3180+
3181+Cleanup:
3182+ if (request)
3183+ {
3184+ PutRndisRequest(Device, request);
3185+ }
3186+ DPRINT_EXIT(NETVSC);
3187+
3188+ return ret;
3189+}
3190+
3191+static void
3192+RndisFilterHaltDevice(
3193+ RNDIS_DEVICE *Device
3194+ )
3195+{
3196+ RNDIS_REQUEST *request;
3197+ RNDIS_HALT_REQUEST *halt;
3198+
3199+ DPRINT_ENTER(NETVSC);
3200+
3201+ // Attempt to do a rndis device halt
3202+ request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST));
3203+ if (!request)
3204+ {
3205+ goto Cleanup;
3206+ }
3207+
3208+ // Setup the rndis set
3209+ halt = &request->RequestMessage.Message.HaltRequest;
3210+ halt->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
3211+
3212+ // Ignore return since this msg is optional.
3213+ RndisFilterSendRequest(Device, request);
3214+
3215+ Device->State = RNDIS_DEV_UNINITIALIZED;
3216+
3217+Cleanup:
3218+ if (request)
3219+ {
3220+ PutRndisRequest(Device, request);
3221+ }
3222+ DPRINT_EXIT(NETVSC);
3223+ return;
3224+}
3225+
3226+
3227+static int
3228+RndisFilterOpenDevice(
3229+ RNDIS_DEVICE *Device
3230+ )
3231+{
3232+ int ret=0;
3233+
3234+ DPRINT_ENTER(NETVSC);
3235+
3236+ if (Device->State != RNDIS_DEV_INITIALIZED)
3237+ return 0;
3238+
3239+ ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
3240+ if (ret == 0)
3241+ {
3242+ Device->State = RNDIS_DEV_DATAINITIALIZED;
3243+ }
3244+
3245+ DPRINT_EXIT(NETVSC);
3246+ return ret;
3247+}
3248+
3249+static int
3250+RndisFilterCloseDevice(
3251+ RNDIS_DEVICE *Device
3252+ )
3253+{
3254+ int ret;
3255+
3256+ DPRINT_ENTER(NETVSC);
3257+
3258+ if (Device->State != RNDIS_DEV_DATAINITIALIZED)
3259+ return 0;
3260+
3261+ ret = RndisFilterSetPacketFilter(Device, 0);
3262+ if (ret == 0)
3263+ {
3264+ Device->State = RNDIS_DEV_INITIALIZED;
3265+ }
3266+
3267+ DPRINT_EXIT(NETVSC);
3268+
3269+ return ret;
3270+}
3271+
3272+
3273+int
3274+RndisFilterOnDeviceAdd(
3275+ DEVICE_OBJECT *Device,
3276+ void *AdditionalInfo
3277+ )
3278+{
3279+ int ret;
3280+ NETVSC_DEVICE *netDevice;
3281+ RNDIS_DEVICE *rndisDevice;
3282+ NETVSC_DEVICE_INFO *deviceInfo = (NETVSC_DEVICE_INFO*)AdditionalInfo;
3283+
3284+ DPRINT_ENTER(NETVSC);
3285+
3286+ //rndisDevice = MemAlloc(sizeof(RNDIS_DEVICE));
3287+ rndisDevice = GetRndisDevice();
3288+ if (!rndisDevice)
3289+ {
3290+ DPRINT_EXIT(NETVSC);
3291+ return -1;
3292+ }
3293+
3294+ DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
3295+
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);
3300+ if (ret != 0)
3301+ {
3302+ PutRndisDevice(rndisDevice);
3303+ DPRINT_EXIT(NETVSC);
3304+ return ret;
3305+ }
3306+
3307+ //
3308+ // Initialize the rndis device
3309+ //
3310+ netDevice = (NETVSC_DEVICE*)Device->Extension;
3311+ ASSERT(netDevice);
3312+ ASSERT(netDevice->Device);
3313+
3314+ netDevice->Extension = rndisDevice;
3315+ rndisDevice->NetDevice = netDevice;
3316+
3317+ // Send the rndis initialization message
3318+ ret = RndisFilterInitDevice(rndisDevice);
3319+ if (ret != 0)
3320+ {
3321+ // TODO: If rndis init failed, we will need to shut down the channel
3322+ }
3323+
3324+ // Get the mac address
3325+ ret = RndisFilterQueryDeviceMac(rndisDevice);
3326+ if (ret != 0)
3327+ {
3328+ // TODO: shutdown rndis device and the channel
3329+ }
3330+
3331+ DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
3332+ rndisDevice,
3333+ rndisDevice->HwMacAddr[0],
3334+ rndisDevice->HwMacAddr[1],
3335+ rndisDevice->HwMacAddr[2],
3336+ rndisDevice->HwMacAddr[3],
3337+ rndisDevice->HwMacAddr[4],
3338+ rndisDevice->HwMacAddr[5]);
3339+
3340+ memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
3341+
3342+ RndisFilterQueryDeviceLinkStatus(rndisDevice);
3343+
3344+ deviceInfo->LinkState = rndisDevice->LinkStatus;
3345+ DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, ((deviceInfo->LinkState)?("down"):("up")));
3346+
3347+ DPRINT_EXIT(NETVSC);
3348+
3349+ return ret;
3350+}
3351+
3352+
3353+static int
3354+RndisFilterOnDeviceRemove(
3355+ DEVICE_OBJECT *Device
3356+ )
3357+{
3358+ NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
3359+ RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
3360+
3361+ DPRINT_ENTER(NETVSC);
3362+
3363+ // Halt and release the rndis device
3364+ RndisFilterHaltDevice(rndisDevice);
3365+
3366+ PutRndisDevice(rndisDevice);
3367+ netDevice->Extension = NULL;
3368+
3369+ // Pass control to inner driver to remove the device
3370+ gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
3371+
3372+ DPRINT_EXIT(NETVSC);
3373+
3374+ return 0;
3375+}
3376+
3377+
3378+static void
3379+RndisFilterOnCleanup(
3380+ DRIVER_OBJECT *Driver
3381+ )
3382+{
3383+ DPRINT_ENTER(NETVSC);
3384+
3385+ DPRINT_EXIT(NETVSC);
3386+}
3387+
3388+static int
3389+RndisFilterOnOpen(
3390+ DEVICE_OBJECT *Device
3391+ )
3392+{
3393+ int ret;
3394+ NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
3395+
3396+ DPRINT_ENTER(NETVSC);
3397+
3398+ ASSERT(netDevice);
3399+ ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
3400+
3401+ DPRINT_EXIT(NETVSC);
3402+
3403+ return ret;
3404+}
3405+
3406+static int
3407+RndisFilterOnClose(
3408+ DEVICE_OBJECT *Device
3409+ )
3410+{
3411+ int ret;
3412+ NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
3413+
3414+ DPRINT_ENTER(NETVSC);
3415+
3416+ ASSERT(netDevice);
3417+ ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
3418+
3419+ DPRINT_EXIT(NETVSC);
3420+
3421+ return ret;
3422+}
3423+
3424+
3425+static int
3426+RndisFilterOnSend(
3427+ DEVICE_OBJECT *Device,
3428+ NETVSC_PACKET *Packet
3429+ )
3430+{
3431+ int ret=0;
3432+ RNDIS_FILTER_PACKET *filterPacket;
3433+ RNDIS_MESSAGE *rndisMessage;
3434+ RNDIS_PACKET *rndisPacket;
3435+ UINT32 rndisMessageSize;
3436+
3437+ DPRINT_ENTER(NETVSC);
3438+
3439+ // Add the rndis header
3440+ filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
3441+ ASSERT(filterPacket);
3442+
3443+ memset(filterPacket, 0, sizeof(RNDIS_FILTER_PACKET));
3444+
3445+ rndisMessage = &filterPacket->Message;
3446+ rndisMessageSize = RNDIS_MESSAGE_SIZE(RNDIS_PACKET);
3447+
3448+ rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
3449+ rndisMessage->MessageLength = Packet->TotalDataBufferLength + rndisMessageSize;
3450+
3451+ rndisPacket = &rndisMessage->Message.Packet;
3452+ rndisPacket->DataOffset = sizeof(RNDIS_PACKET);
3453+ rndisPacket->DataLength = Packet->TotalDataBufferLength;
3454+
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;
3459+
3460+ // Save the packet send completion and context
3461+ filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
3462+ filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
3463+
3464+ // Use ours
3465+ Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
3466+ Packet->Completion.Send.SendCompletionContext = filterPacket;
3467+
3468+ ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
3469+ if (ret != 0)
3470+ {
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;
3474+ }
3475+
3476+ DPRINT_EXIT(NETVSC);
3477+
3478+ return ret;
3479+}
3480+
3481+static void
3482+RndisFilterOnSendCompletion(
3483+ void *Context)
3484+{
3485+ RNDIS_FILTER_PACKET *filterPacket = (RNDIS_FILTER_PACKET *)Context;
3486+
3487+ DPRINT_ENTER(NETVSC);
3488+
3489+ // Pass it back to the original handler
3490+ filterPacket->OnCompletion(filterPacket->CompletionContext);
3491+
3492+ DPRINT_EXIT(NETVSC);
3493+}
3494+
3495+
3496+static void
3497+RndisFilterOnSendRequestCompletion(
3498+ void *Context
3499+ )
3500+{
3501+ DPRINT_ENTER(NETVSC);
3502+
3503+ // Noop
3504+ DPRINT_EXIT(NETVSC);
3505+}
3506--- /dev/null
3507+++ b/drivers/staging/hv/RndisFilter.h
3508@@ -0,0 +1,61 @@
3509+/*
3510+ *
3511+ * Copyright (c) 2009, Microsoft Corporation.
3512+ *
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.
3516+ *
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
3520+ * more details.
3521+ *
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.
3525+ *
3526+ * Authors:
3527+ * Haiyang Zhang <haiyangz@microsoft.com>
3528+ * Hank Janssen <hjanssen@microsoft.com>
3529+ *
3530+ */
3531+
3532+
3533+#ifndef _RNDISFILTER_H_
3534+#define _RNDISFILTER_H_
3535+
3536+#define __struct_bcount(x)
3537+
3538+#include "osd.h"
3539+#include "NetVsc.h"
3540+
3541+#include "rndis.h"
3542+
3543+#define RNDIS_HEADER_SIZE (sizeof(RNDIS_MESSAGE) - sizeof(RNDIS_MESSAGE_CONTAINER))
3544+
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
3557+
3558+
3559+
3560+//
3561+// Interface
3562+//
3563+int
3564+RndisFilterInit(
3565+ NETVSC_DRIVER_OBJECT *Driver
3566+ );
3567+
3568+
3569+#endif // _RNDISFILTER_H_