]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.drivers/staging-hv-add-the-hyper-v-virtual-network-driver.patch
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / staging-hv-add-the-hyper-v-virtual-network-driver.patch
1 From fec8755b6193c93a935423fdd6026b354aa2e15e Mon Sep 17 00:00:00 2001
2 From: Hank Janssen <hjanssen@microsoft.com>
3 Date: Mon, 13 Jul 2009 15:34:54 -0700
4 Subject: Staging: hv: add the Hyper-V virtual network driver
5
6 From: Hank Janssen <hjanssen@microsoft.com>
7
8 This is the virtual network driver when running Linux on top of Hyper-V.
9
10 Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
11 Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
12 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
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_