Staging: hv: remove PAGE_SIZE and PAGE_SHIFT and __builtin functions
[safe/jmp/linux-2.6] / drivers / staging / hv / NetVsc.c
1 /*
2  *
3  * Copyright (c) 2009, Microsoft Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16  * Place - Suite 330, Boston, MA 02111-1307 USA.
17  *
18  * Authors:
19  *   Hank Janssen  <hjanssen@microsoft.com>
20  *
21  */
22
23 #define KERNEL_2_6_27
24
25 #include <linux/kernel.h>
26 #include <linux/mm.h>
27 #include "include/logging.h"
28 #include "NetVsc.h"
29 #include "RndisFilter.h"
30
31
32 //
33 // Globals
34 //
35 static const char* gDriverName="netvsc";
36
37 // {F8615163-DF3E-46c5-913F-F2D2F965ED0E}
38 static const GUID gNetVscDeviceType={
39         .Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
40 };
41
42
43 //
44 // Internal routines
45 //
46 static int
47 NetVscOnDeviceAdd(
48         DEVICE_OBJECT   *Device,
49         void                    *AdditionalInfo
50         );
51
52 static int
53 NetVscOnDeviceRemove(
54         DEVICE_OBJECT *Device
55         );
56
57 static void
58 NetVscOnCleanup(
59         DRIVER_OBJECT *Driver
60         );
61
62 static void
63 NetVscOnChannelCallback(
64         void * context
65         );
66
67 static int
68 NetVscInitializeSendBufferWithNetVsp(
69         DEVICE_OBJECT                   *Device
70         );
71
72 static int
73 NetVscInitializeReceiveBufferWithNetVsp(
74         DEVICE_OBJECT                   *Device
75         );
76
77 static int
78 NetVscDestroySendBuffer(
79         NETVSC_DEVICE   *NetDevice
80         );
81
82 static int
83 NetVscDestroyReceiveBuffer(
84         NETVSC_DEVICE   *NetDevice
85         );
86
87 static int
88 NetVscConnectToVsp(
89         DEVICE_OBJECT           *Device
90         );
91
92 static void
93 NetVscOnSendCompletion(
94         DEVICE_OBJECT           *Device,
95         VMPACKET_DESCRIPTOR *Packet
96         );
97
98 static int
99 NetVscOnSend(
100         DEVICE_OBJECT   *Device,
101         NETVSC_PACKET   *Packet
102         );
103
104 static void
105 NetVscOnReceive(
106         DEVICE_OBJECT           *Device,
107         VMPACKET_DESCRIPTOR *Packet
108         );
109
110 static void
111 NetVscOnReceiveCompletion(
112         void * Context
113         );
114
115 static void
116 NetVscSendReceiveCompletion(
117         DEVICE_OBJECT   *Device,
118         u64                     TransactionId
119         );
120
121 static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
122 {
123         NETVSC_DEVICE *netDevice;
124
125         netDevice = MemAllocZeroed(sizeof(NETVSC_DEVICE));
126         if (!netDevice)
127                 return NULL;
128
129         // Set to 2 to allow both inbound and outbound traffic
130         InterlockedCompareExchange(&netDevice->RefCount, 2, 0);
131
132         netDevice->Device = Device;
133         Device->Extension = netDevice;
134
135         return netDevice;
136 }
137
138 static inline void FreeNetDevice(NETVSC_DEVICE *Device)
139 {
140         ASSERT(Device->RefCount == 0);
141         Device->Device->Extension = NULL;
142         MemFree(Device);
143 }
144
145
146 // Get the net device object iff exists and its refcount > 1
147 static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT *Device)
148 {
149         NETVSC_DEVICE *netDevice;
150
151         netDevice = (NETVSC_DEVICE*)Device->Extension;
152         if (netDevice && netDevice->RefCount > 1)
153         {
154                 InterlockedIncrement(&netDevice->RefCount);
155         }
156         else
157         {
158                 netDevice = NULL;
159         }
160
161         return netDevice;
162 }
163
164 // Get the net device object iff exists and its refcount > 0
165 static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT  *Device)
166 {
167         NETVSC_DEVICE *netDevice;
168
169         netDevice = (NETVSC_DEVICE*)Device->Extension;
170         if (netDevice && netDevice->RefCount)
171         {
172                 InterlockedIncrement(&netDevice->RefCount);
173         }
174         else
175         {
176                 netDevice = NULL;
177         }
178
179         return netDevice;
180 }
181
182 static inline void PutNetDevice(DEVICE_OBJECT *Device)
183 {
184         NETVSC_DEVICE *netDevice;
185
186         netDevice = (NETVSC_DEVICE*)Device->Extension;
187         ASSERT(netDevice);
188
189         InterlockedDecrement(&netDevice->RefCount);
190 }
191
192 static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
193 {
194         NETVSC_DEVICE *netDevice;
195
196         netDevice = (NETVSC_DEVICE*)Device->Extension;
197         if (netDevice == NULL)
198                 return NULL;
199
200         // Busy wait until the ref drop to 2, then set it to 1
201         while (InterlockedCompareExchange(&netDevice->RefCount, 1, 2) != 2)
202         {
203                 Sleep(100);
204         }
205
206         return netDevice;
207 }
208
209 static inline NETVSC_DEVICE* ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
210 {
211         NETVSC_DEVICE *netDevice;
212
213         netDevice = (NETVSC_DEVICE*)Device->Extension;
214         if (netDevice == NULL)
215                 return NULL;
216
217         // Busy wait until the ref drop to 1, then set it to 0
218         while (InterlockedCompareExchange(&netDevice->RefCount, 0, 1) != 1)
219         {
220                 Sleep(100);
221         }
222
223         Device->Extension = NULL;
224         return netDevice;
225 }
226
227 /*++;
228
229
230 Name:
231         NetVscInitialize()
232
233 Description:
234         Main entry point
235
236 --*/
237 int
238 NetVscInitialize(
239         DRIVER_OBJECT *drv
240         )
241 {
242         NETVSC_DRIVER_OBJECT* driver = (NETVSC_DRIVER_OBJECT*)drv;
243         int ret=0;
244
245         DPRINT_ENTER(NETVSC);
246
247         DPRINT_DBG(NETVSC, "sizeof(NETVSC_PACKET)=%d, sizeof(NVSP_MESSAGE)=%d, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%d",
248                 sizeof(NETVSC_PACKET), sizeof(NVSP_MESSAGE), sizeof(VMTRANSFER_PAGE_PACKET_HEADER));
249
250         // Make sure we are at least 2 pages since 1 page is used for control
251         ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));
252
253         drv->name = gDriverName;
254         memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(GUID));
255
256         // Make sure it is set by the caller
257         ASSERT(driver->OnReceiveCallback);
258         ASSERT(driver->OnLinkStatusChanged);
259
260         // Setup the dispatch table
261         driver->Base.OnDeviceAdd                = NetVscOnDeviceAdd;
262         driver->Base.OnDeviceRemove             = NetVscOnDeviceRemove;
263         driver->Base.OnCleanup                  = NetVscOnCleanup;
264
265         driver->OnSend                                  = NetVscOnSend;
266
267         RndisFilterInit(driver);
268
269         DPRINT_EXIT(NETVSC);
270
271         return ret;
272 }
273
274 static int
275 NetVscInitializeReceiveBufferWithNetVsp(
276         DEVICE_OBJECT   *Device
277         )
278 {
279         int ret=0;
280         NETVSC_DEVICE *netDevice;
281         NVSP_MESSAGE *initPacket;
282
283         DPRINT_ENTER(NETVSC);
284
285         netDevice = GetOutboundNetDevice(Device);
286         if (!netDevice)
287         {
288                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
289                 DPRINT_EXIT(NETVSC);
290                 return -1;
291         }
292         ASSERT(netDevice->ReceiveBufferSize > 0);
293         ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
294
295         netDevice->ReceiveBuffer = PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
296         if (!netDevice->ReceiveBuffer)
297         {
298                 DPRINT_ERR(NETVSC, "unable to allocate receive buffer of size %d", netDevice->ReceiveBufferSize);
299                 ret = -1;
300                 goto Cleanup;
301         }
302         ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
303
304         DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
305
306         // Establish the gpadl handle for this buffer on this channel.
307         // Note: This call uses the vmbus connection rather than the channel to establish
308         // the gpadl handle.
309         ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
310                                                                                                                                 netDevice->ReceiveBuffer,
311                                                                                                                                 netDevice->ReceiveBufferSize,
312                                                                                                                                 &netDevice->ReceiveBufferGpadlHandle);
313
314         if (ret != 0)
315         {
316                 DPRINT_ERR(NETVSC, "unable to establish receive buffer's gpadl");
317                 goto Cleanup;
318         }
319
320         //WaitEventWait(ext->ChannelInitEvent);
321
322         // Notify the NetVsp of the gpadl handle
323         DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
324
325         initPacket = &netDevice->ChannelInitPacket;
326
327         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
328
329     initPacket->Header.MessageType = NvspMessage1TypeSendReceiveBuffer;
330     initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle;
331     initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
332
333         // Send the gpadl notification request
334         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
335                                                                                                                         initPacket,
336                                                                                                                         sizeof(NVSP_MESSAGE),
337                                                                                                                         (unsigned long)initPacket,
338                                                                                                                         VmbusPacketTypeDataInBand,
339                                                                                                                         VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
340         if (ret != 0)
341         {
342                 DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
343                 goto Cleanup;
344         }
345
346         WaitEventWait(netDevice->ChannelInitEvent);
347
348         // Check the response
349         if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess)
350         {
351                 DPRINT_ERR(NETVSC,
352                         "Unable to complete receive buffer initialzation with NetVsp - status %d",
353                         initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status);
354                 ret = -1;
355                 goto Cleanup;
356         }
357
358         // Parse the response
359         ASSERT(netDevice->ReceiveSectionCount == 0);
360         ASSERT(netDevice->ReceiveSections == NULL);
361
362         netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections;
363
364         netDevice->ReceiveSections = MemAlloc(netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
365         if (netDevice->ReceiveSections == NULL)
366         {
367                 ret = -1;
368                 goto Cleanup;
369         }
370
371         memcpy(netDevice->ReceiveSections,
372                 initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Sections,
373                 netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
374
375         DPRINT_INFO(NETVSC,
376                 "Receive sections info (count %d, offset %d, endoffset %d, suballoc size %d, num suballocs %d)",
377                 netDevice->ReceiveSectionCount, netDevice->ReceiveSections[0].Offset, netDevice->ReceiveSections[0].EndOffset,
378                 netDevice->ReceiveSections[0].SubAllocationSize, netDevice->ReceiveSections[0].NumSubAllocations);
379
380
381         //For 1st release, there should only be 1 section that represents the entire receive buffer
382         if (netDevice->ReceiveSectionCount != 1 ||
383                 netDevice->ReceiveSections->Offset != 0 )
384         {
385                 ret = -1;
386                 goto Cleanup;
387         }
388
389         goto Exit;
390
391 Cleanup:
392         NetVscDestroyReceiveBuffer(netDevice);
393
394 Exit:
395         PutNetDevice(Device);
396         DPRINT_EXIT(NETVSC);
397         return ret;
398 }
399
400
401 static int
402 NetVscInitializeSendBufferWithNetVsp(
403         DEVICE_OBJECT   *Device
404         )
405 {
406         int ret=0;
407         NETVSC_DEVICE *netDevice;
408         NVSP_MESSAGE *initPacket;
409
410         DPRINT_ENTER(NETVSC);
411
412         netDevice = GetOutboundNetDevice(Device);
413         if (!netDevice)
414         {
415                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
416                 DPRINT_EXIT(NETVSC);
417                 return -1;
418         }
419         ASSERT(netDevice->SendBufferSize > 0);
420         ASSERT((netDevice->SendBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
421
422         netDevice->SendBuffer = PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
423         if (!netDevice->SendBuffer)
424         {
425                 DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d", netDevice->SendBufferSize);
426                 ret = -1;
427                 goto Cleanup;
428         }
429         ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
430
431         DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
432
433         // Establish the gpadl handle for this buffer on this channel.
434         // Note: This call uses the vmbus connection rather than the channel to establish
435         // the gpadl handle.
436         ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
437                                                                                                                                 netDevice->SendBuffer,
438                                                                                                                                 netDevice->SendBufferSize,
439                                                                                                                                 &netDevice->SendBufferGpadlHandle);
440
441         if (ret != 0)
442         {
443                 DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
444                 goto Cleanup;
445         }
446
447         //WaitEventWait(ext->ChannelInitEvent);
448
449         // Notify the NetVsp of the gpadl handle
450         DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
451
452         initPacket = &netDevice->ChannelInitPacket;
453
454         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
455
456     initPacket->Header.MessageType = NvspMessage1TypeSendSendBuffer;
457     initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle;
458     initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID;
459
460         // Send the gpadl notification request
461         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
462                                                                                                                         initPacket,
463                                                                                                                         sizeof(NVSP_MESSAGE),
464                                                                                                                         (unsigned long)initPacket,
465                                                                                                                         VmbusPacketTypeDataInBand,
466                                                                                                                         VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
467         if (ret != 0)
468         {
469                 DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
470                 goto Cleanup;
471         }
472
473         WaitEventWait(netDevice->ChannelInitEvent);
474
475         // Check the response
476         if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess)
477         {
478                 DPRINT_ERR(NETVSC,
479                         "Unable to complete send buffer initialzation with NetVsp - status %d",
480                         initPacket->Messages.Version1Messages.SendSendBufferComplete.Status);
481                 ret = -1;
482                 goto Cleanup;
483         }
484
485         netDevice->SendSectionSize = initPacket->Messages.Version1Messages.SendSendBufferComplete.SectionSize;
486
487         goto Exit;
488
489 Cleanup:
490         NetVscDestroySendBuffer(netDevice);
491
492 Exit:
493         PutNetDevice(Device);
494         DPRINT_EXIT(NETVSC);
495         return ret;
496 }
497
498 static int
499 NetVscDestroyReceiveBuffer(
500         NETVSC_DEVICE   *NetDevice
501         )
502 {
503         NVSP_MESSAGE *revokePacket;
504         int ret=0;
505
506
507         DPRINT_ENTER(NETVSC);
508
509         // If we got a section count, it means we received a SendReceiveBufferComplete msg
510         // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
511         if (NetDevice->ReceiveSectionCount)
512         {
513                 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
514
515                 // Send the revoke receive buffer
516                 revokePacket = &NetDevice->RevokePacket;
517                 memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
518
519                 revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer;
520                 revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
521
522                 ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
523                                                                                                                                                         revokePacket,
524                                                                                                                                                         sizeof(NVSP_MESSAGE),
525                                                                                                                                                         (unsigned long)revokePacket,
526                                                                                                                                                         VmbusPacketTypeDataInBand,
527                                                                                                                                                         0);
528                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
529                 if (ret != 0)
530                 {
531                         DPRINT_ERR(NETVSC, "unable to send revoke receive buffer to netvsp");
532                         DPRINT_EXIT(NETVSC);
533                         return -1;
534                 }
535         }
536
537         // Teardown the gpadl on the vsp end
538         if (NetDevice->ReceiveBufferGpadlHandle)
539         {
540                 DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
541
542                 ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
543                                                                                                                                                                 NetDevice->ReceiveBufferGpadlHandle);
544
545                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
546                 if (ret != 0)
547                 {
548                         DPRINT_ERR(NETVSC, "unable to teardown receive buffer's gpadl");
549                         DPRINT_EXIT(NETVSC);
550                         return -1;
551                 }
552                 NetDevice->ReceiveBufferGpadlHandle = 0;
553         }
554
555         if (NetDevice->ReceiveBuffer)
556         {
557                 DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
558
559                 // Free up the receive buffer
560                 PageFree(NetDevice->ReceiveBuffer, NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
561                 NetDevice->ReceiveBuffer = NULL;
562         }
563
564         if (NetDevice->ReceiveSections)
565         {
566                 MemFree(NetDevice->ReceiveSections);
567                 NetDevice->ReceiveSections = NULL;
568                 NetDevice->ReceiveSectionCount = 0;
569         }
570
571         DPRINT_EXIT(NETVSC);
572
573         return ret;
574 }
575
576
577
578
579 static int
580 NetVscDestroySendBuffer(
581         NETVSC_DEVICE   *NetDevice
582         )
583 {
584         NVSP_MESSAGE *revokePacket;
585         int ret=0;
586
587
588         DPRINT_ENTER(NETVSC);
589
590         // If we got a section count, it means we received a SendReceiveBufferComplete msg
591         // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
592         if (NetDevice->SendSectionSize)
593         {
594                 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeSendBuffer...");
595
596                 // Send the revoke send buffer
597                 revokePacket = &NetDevice->RevokePacket;
598                 memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
599
600                 revokePacket->Header.MessageType = NvspMessage1TypeRevokeSendBuffer;
601                 revokePacket->Messages.Version1Messages.RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID;
602
603                 ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
604                                                                                                                                                         revokePacket,
605                                                                                                                                                         sizeof(NVSP_MESSAGE),
606                                                                                                                                                         (unsigned long)revokePacket,
607                                                                                                                                                         VmbusPacketTypeDataInBand,
608                                                                                                                                                         0);
609                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
610                 if (ret != 0)
611                 {
612                         DPRINT_ERR(NETVSC, "unable to send revoke send buffer to netvsp");
613                         DPRINT_EXIT(NETVSC);
614                         return -1;
615                 }
616         }
617
618         // Teardown the gpadl on the vsp end
619         if (NetDevice->SendBufferGpadlHandle)
620         {
621                 DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
622
623                 ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
624                                                                                                                                                                 NetDevice->SendBufferGpadlHandle);
625
626                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
627                 if (ret != 0)
628                 {
629                         DPRINT_ERR(NETVSC, "unable to teardown send buffer's gpadl");
630                         DPRINT_EXIT(NETVSC);
631                         return -1;
632                 }
633                 NetDevice->SendBufferGpadlHandle = 0;
634         }
635
636         if (NetDevice->SendBuffer)
637         {
638                 DPRINT_INFO(NETVSC, "Freeing up send buffer...");
639
640                 // Free up the receive buffer
641                 PageFree(NetDevice->SendBuffer, NetDevice->SendBufferSize >> PAGE_SHIFT);
642                 NetDevice->SendBuffer = NULL;
643         }
644
645         DPRINT_EXIT(NETVSC);
646
647         return ret;
648 }
649
650
651
652 static int
653 NetVscConnectToVsp(
654         DEVICE_OBJECT   *Device
655         )
656 {
657         int ret=0;
658         NETVSC_DEVICE *netDevice;
659         NVSP_MESSAGE *initPacket;
660         int ndisVersion;
661
662         DPRINT_ENTER(NETVSC);
663
664         netDevice = GetOutboundNetDevice(Device);
665         if (!netDevice)
666         {
667                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
668                 DPRINT_EXIT(NETVSC);
669                 return -1;
670         }
671
672         initPacket = &netDevice->ChannelInitPacket;
673
674         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
675         initPacket->Header.MessageType = NvspMessageTypeInit;
676     initPacket->Messages.InitMessages.Init.MinProtocolVersion = NVSP_MIN_PROTOCOL_VERSION;
677     initPacket->Messages.InitMessages.Init.MaxProtocolVersion = NVSP_MAX_PROTOCOL_VERSION;
678
679         DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
680
681         // Send the init request
682         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
683                                                                                                                         initPacket,
684                                                                                                                         sizeof(NVSP_MESSAGE),
685                                                                                                                         (unsigned long)initPacket,
686                                                                                                                         VmbusPacketTypeDataInBand,
687                                                                                                                         VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
688
689         if( ret != 0)
690         {
691                 DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
692                 goto Cleanup;
693         }
694
695         WaitEventWait(netDevice->ChannelInitEvent);
696
697         // Now, check the response
698         //ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT);
699         DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
700                 initPacket->Messages.InitMessages.InitComplete.Status,
701                 initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength);
702
703         if (initPacket->Messages.InitMessages.InitComplete.Status != NvspStatusSuccess)
704         {
705                 DPRINT_ERR(NETVSC, "unable to initialize with netvsp (status 0x%x)", initPacket->Messages.InitMessages.InitComplete.Status);
706                 ret = -1;
707                 goto Cleanup;
708         }
709
710         if (initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1)
711         {
712                 DPRINT_ERR(NETVSC, "unable to initialize with netvsp (version expected 1 got %d)",
713                         initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion);
714                 ret = -1;
715                 goto Cleanup;
716         }
717         DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
718
719         // Send the ndis version
720         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
721
722     ndisVersion = 0x00050000;
723
724     initPacket->Header.MessageType = NvspMessage1TypeSendNdisVersion;
725     initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion = (ndisVersion & 0xFFFF0000) >> 16;
726     initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion = ndisVersion & 0xFFFF;
727
728         // Send the init request
729         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
730                                                                                                                         initPacket,
731                                                                                                                         sizeof(NVSP_MESSAGE),
732                                                                                                                         (unsigned long)initPacket,
733                                                                                                                         VmbusPacketTypeDataInBand,
734                                                                                                                         0);
735         if (ret != 0)
736         {
737                 DPRINT_ERR(NETVSC, "unable to send NvspMessage1TypeSendNdisVersion");
738                 ret = -1;
739                 goto Cleanup;
740         }
741         //
742         // BUGBUG - We have to wait for the above msg since the netvsp uses KMCL which acknowledges packet (completion packet)
743         // since our Vmbus always set the VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
744         //WaitEventWait(NetVscChannel->ChannelInitEvent);
745
746         // Post the big receive buffer to NetVSP
747         ret = NetVscInitializeReceiveBufferWithNetVsp(Device);
748         if (ret == 0)
749         {
750                 ret = NetVscInitializeSendBufferWithNetVsp(Device);
751         }
752
753 Cleanup:
754         PutNetDevice(Device);
755         DPRINT_EXIT(NETVSC);
756         return ret;
757 }
758
759 static void
760 NetVscDisconnectFromVsp(
761         NETVSC_DEVICE   *NetDevice
762         )
763 {
764         DPRINT_ENTER(NETVSC);
765
766         NetVscDestroyReceiveBuffer(NetDevice);
767         NetVscDestroySendBuffer(NetDevice);
768
769         DPRINT_EXIT(NETVSC);
770 }
771
772
773 /*++
774
775 Name:
776         NetVscOnDeviceAdd()
777
778 Description:
779         Callback when the device belonging to this driver is added
780
781 --*/
782 int
783 NetVscOnDeviceAdd(
784         DEVICE_OBJECT   *Device,
785         void                    *AdditionalInfo
786         )
787 {
788         int ret=0;
789         int i;
790
791         NETVSC_DEVICE* netDevice;
792         NETVSC_PACKET* packet;
793         LIST_ENTRY *entry;
794
795         NETVSC_DRIVER_OBJECT *netDriver = (NETVSC_DRIVER_OBJECT*) Device->Driver;;
796
797         DPRINT_ENTER(NETVSC);
798
799         netDevice = AllocNetDevice(Device);
800         if (!netDevice)
801         {
802                 ret = -1;
803                 goto Cleanup;
804         }
805
806         DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice);
807
808         // Initialize the NetVSC channel extension
809         netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
810         netDevice->ReceivePacketListLock = SpinlockCreate();
811
812         netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
813
814         INITIALIZE_LIST_HEAD(&netDevice->ReceivePacketList);
815
816         for (i=0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++)
817         {
818                 packet = MemAllocZeroed(sizeof(NETVSC_PACKET) + (NETVSC_RECEIVE_SG_COUNT* sizeof(PAGE_BUFFER)));
819                 if (!packet)
820                 {
821                         DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT, i);
822                         break;
823                 }
824
825                 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
826         }
827         netDevice->ChannelInitEvent = WaitEventCreate();
828
829         // Open the channel
830         ret = Device->Driver->VmbusChannelInterface.Open(Device,
831                                                                                                                 netDriver->RingBufferSize,
832                                                                                                                 netDriver->RingBufferSize,
833                                                                                                                 NULL, 0,
834                                                                                                                 NetVscOnChannelCallback,
835                                                                                                                 Device
836                                                                                                                 );
837
838         if (ret != 0)
839         {
840                 DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
841                 ret = -1;
842                 goto Cleanup;
843         }
844
845         // Channel is opened
846         DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
847
848         // Connect with the NetVsp
849         ret = NetVscConnectToVsp(Device);
850         if (ret != 0)
851         {
852                 DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret);
853                 ret = -1;
854                 goto Close;
855         }
856
857         DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***", ret);
858
859         DPRINT_EXIT(NETVSC);
860         return ret;
861
862 Close:
863         // Now, we can close the channel safely
864         Device->Driver->VmbusChannelInterface.Close(Device);
865
866 Cleanup:
867
868         if (netDevice)
869         {
870                 WaitEventClose(netDevice->ChannelInitEvent);
871
872                 while (!IsListEmpty(&netDevice->ReceivePacketList))
873                 {
874                         entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
875                         packet = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
876                         MemFree(packet);
877                 }
878
879                 SpinlockClose(netDevice->ReceivePacketListLock);
880
881                 ReleaseOutboundNetDevice(Device);
882                 ReleaseInboundNetDevice(Device);
883
884                 FreeNetDevice(netDevice);
885         }
886
887         DPRINT_EXIT(NETVSC);
888         return ret;
889 }
890
891
892 /*++
893
894 Name:
895         NetVscOnDeviceRemove()
896
897 Description:
898         Callback when the root bus device is removed
899
900 --*/
901 int
902 NetVscOnDeviceRemove(
903         DEVICE_OBJECT *Device
904         )
905 {
906         NETVSC_DEVICE *netDevice;
907         NETVSC_PACKET *netvscPacket;
908         int ret=0;
909         LIST_ENTRY *entry;
910
911         DPRINT_ENTER(NETVSC);
912
913         DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...", Device->Extension);
914
915         // Stop outbound traffic ie sends and receives completions
916         netDevice = ReleaseOutboundNetDevice(Device);
917         if (!netDevice)
918         {
919                 DPRINT_ERR(NETVSC, "No net device present!!");
920                 return -1;
921         }
922
923         // Wait for all send completions
924         while (netDevice->NumOutstandingSends)
925         {
926                 DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", netDevice->NumOutstandingSends);
927
928                 Sleep(100);
929         }
930
931         DPRINT_INFO(NETVSC, "Disconnecting from netvsp...");
932
933         NetVscDisconnectFromVsp(netDevice);
934
935         DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...", Device->Extension);
936
937         // Stop inbound traffic ie receives and sends completions
938         netDevice = ReleaseInboundNetDevice(Device);
939
940         // At this point, no one should be accessing netDevice except in here
941         DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice);
942
943         // Now, we can close the channel safely
944         Device->Driver->VmbusChannelInterface.Close(Device);
945
946         // Release all resources
947         while (!IsListEmpty(&netDevice->ReceivePacketList))
948         {
949                 entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
950                 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
951
952                 MemFree(netvscPacket);
953         }
954
955         SpinlockClose(netDevice->ReceivePacketListLock);
956         WaitEventClose(netDevice->ChannelInitEvent);
957         FreeNetDevice(netDevice);
958
959         DPRINT_EXIT(NETVSC);
960         return ret;
961 }
962
963
964
965 /*++
966
967 Name:
968         NetVscOnCleanup()
969
970 Description:
971         Perform any cleanup when the driver is removed
972
973 --*/
974 void
975 NetVscOnCleanup(
976         DRIVER_OBJECT *drv
977         )
978 {
979         DPRINT_ENTER(NETVSC);
980
981         DPRINT_EXIT(NETVSC);
982 }
983
984 static void
985 NetVscOnSendCompletion(
986         DEVICE_OBJECT           *Device,
987         VMPACKET_DESCRIPTOR *Packet
988         )
989 {
990         NETVSC_DEVICE* netDevice;
991         NVSP_MESSAGE *nvspPacket;
992         NETVSC_PACKET *nvscPacket;
993
994         DPRINT_ENTER(NETVSC);
995
996         netDevice = GetInboundNetDevice(Device);
997         if (!netDevice)
998         {
999                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1000                 DPRINT_EXIT(NETVSC);
1001                 return;
1002         }
1003
1004         nvspPacket = (NVSP_MESSAGE*)((unsigned long)Packet + (Packet->DataOffset8 << 3));
1005
1006         DPRINT_DBG(NETVSC, "send completion packet - type %d", nvspPacket->Header.MessageType);
1007
1008         if (nvspPacket->Header.MessageType == NvspMessageTypeInitComplete ||
1009                 nvspPacket->Header.MessageType == NvspMessage1TypeSendReceiveBufferComplete ||
1010                 nvspPacket->Header.MessageType == NvspMessage1TypeSendSendBufferComplete)
1011         {
1012                 // Copy the response back
1013                 memcpy(&netDevice->ChannelInitPacket, nvspPacket, sizeof(NVSP_MESSAGE));
1014                 WaitEventSet(netDevice->ChannelInitEvent);
1015         }
1016         else if (nvspPacket->Header.MessageType == NvspMessage1TypeSendRNDISPacketComplete)
1017         {
1018                 // Get the send context
1019                 nvscPacket = (NETVSC_PACKET *)(unsigned long)Packet->TransactionId;
1020                 ASSERT(nvscPacket);
1021
1022                 // Notify the layer above us
1023                 nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
1024
1025                 InterlockedDecrement(&netDevice->NumOutstandingSends);
1026         }
1027         else
1028         {
1029                 DPRINT_ERR(NETVSC, "Unknown send completion packet type - %d received!!", nvspPacket->Header.MessageType);
1030         }
1031
1032         PutNetDevice(Device);
1033         DPRINT_EXIT(NETVSC);
1034 }
1035
1036
1037
1038 static int
1039 NetVscOnSend(
1040         DEVICE_OBJECT *Device,
1041         NETVSC_PACKET *Packet
1042         )
1043 {
1044         NETVSC_DEVICE* netDevice;
1045         int ret=0;
1046
1047         NVSP_MESSAGE sendMessage;
1048
1049         DPRINT_ENTER(NETVSC);
1050
1051         netDevice = GetOutboundNetDevice(Device);
1052         if (!netDevice)
1053         {
1054                 DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring outbound packets", netDevice);
1055                 DPRINT_EXIT(NETVSC);
1056                 return -2;
1057         }
1058
1059         sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
1060         if (Packet->IsDataPacket)
1061             sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;// 0 is RMC_DATA;
1062         else
1063                 sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;// 1 is RMC_CONTROL;
1064
1065         // Not using send buffer section
1066     sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
1067     sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
1068
1069         if (Packet->PageBufferCount)
1070         {
1071                 ret = Device->Driver->VmbusChannelInterface.SendPacketPageBuffer(Device,
1072                                                                                                                                                         Packet->PageBuffers,
1073                                                                                                                                                         Packet->PageBufferCount,
1074                                                                                                                                                         &sendMessage,
1075                                                                                                                                                         sizeof(NVSP_MESSAGE),
1076                                                                                                                                                         (unsigned long)Packet);
1077         }
1078         else
1079         {
1080                 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1081                                                                                                                                 &sendMessage,
1082                                                                                                                                 sizeof(NVSP_MESSAGE),
1083                                                                                                                                 (unsigned long)Packet,
1084                                                                                                                                 VmbusPacketTypeDataInBand,
1085                                                                                                                                 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1086
1087         }
1088
1089         if (ret != 0)
1090         {
1091                 DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d", Packet, ret);
1092         }
1093
1094         InterlockedIncrement(&netDevice->NumOutstandingSends);
1095         PutNetDevice(Device);
1096
1097         DPRINT_EXIT(NETVSC);
1098         return ret;
1099 }
1100
1101
1102 static void
1103 NetVscOnReceive(
1104         DEVICE_OBJECT           *Device,
1105         VMPACKET_DESCRIPTOR *Packet
1106         )
1107 {
1108         NETVSC_DEVICE* netDevice;
1109         VMTRANSFER_PAGE_PACKET_HEADER *vmxferpagePacket;
1110         NVSP_MESSAGE *nvspPacket;
1111         NETVSC_PACKET *netvscPacket=NULL;
1112         LIST_ENTRY* entry;
1113         unsigned long start;
1114         unsigned long end, endVirtual;
1115         //NETVSC_DRIVER_OBJECT *netvscDriver;
1116         XFERPAGE_PACKET *xferpagePacket=NULL;
1117         LIST_ENTRY listHead;
1118
1119         int i=0, j=0;
1120         int count=0, bytesRemain=0;
1121
1122         DPRINT_ENTER(NETVSC);
1123
1124         netDevice = GetInboundNetDevice(Device);
1125         if (!netDevice)
1126         {
1127                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1128                 DPRINT_EXIT(NETVSC);
1129                 return;
1130         }
1131
1132         // All inbound packets other than send completion should be xfer page packet
1133         if (Packet->Type != VmbusPacketTypeDataUsingTransferPages)
1134         {
1135                 DPRINT_ERR(NETVSC, "Unknown packet type received - %d", Packet->Type);
1136                 PutNetDevice(Device);
1137                 return;
1138         }
1139
1140         nvspPacket = (NVSP_MESSAGE*)((unsigned long)Packet + (Packet->DataOffset8 << 3));
1141
1142         // Make sure this is a valid nvsp packet
1143         if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket )
1144         {
1145                 DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d", nvspPacket->Header.MessageType);
1146                 PutNetDevice(Device);
1147                 return;
1148         }
1149
1150         DPRINT_DBG(NETVSC, "NVSP packet received - type %d", nvspPacket->Header.MessageType);
1151
1152         vmxferpagePacket = (VMTRANSFER_PAGE_PACKET_HEADER*)Packet;
1153
1154         if (vmxferpagePacket->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID)
1155         {
1156                 DPRINT_ERR(NETVSC, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, vmxferpagePacket->TransferPageSetId);
1157                 PutNetDevice(Device);
1158                 return;
1159         }
1160
1161         DPRINT_DBG(NETVSC, "xfer page - range count %d", vmxferpagePacket->RangeCount);
1162
1163         INITIALIZE_LIST_HEAD(&listHead);
1164
1165         // Grab free packets (range count + 1) to represent this xfer page packet. +1 to represent
1166         // the xfer page packet itself. We grab it here so that we know exactly how many we can fulfil
1167         SpinlockAcquire(netDevice->ReceivePacketListLock);
1168         while (!IsListEmpty(&netDevice->ReceivePacketList))
1169         {
1170                 entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
1171                 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1172
1173                 INSERT_TAIL_LIST(&listHead, &netvscPacket->ListEntry);
1174
1175                 if (++count == vmxferpagePacket->RangeCount + 1)
1176                         break;
1177         }
1178         SpinlockRelease(netDevice->ReceivePacketListLock);
1179
1180         // We need at least 2 netvsc pkts (1 to represent the xfer page and at least 1 for the range)
1181         // i.e. we can handled some of the xfer page packet ranges...
1182         if (count < 2)
1183         {
1184                 DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count, vmxferpagePacket->RangeCount+1);
1185
1186                 // Return it to the freelist
1187                 SpinlockAcquire(netDevice->ReceivePacketListLock);
1188                 for (i=count; i != 0; i--)
1189                 {
1190                         entry = REMOVE_HEAD_LIST(&listHead);
1191                         netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1192
1193                         INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &netvscPacket->ListEntry);
1194                 }
1195                 SpinlockRelease(netDevice->ReceivePacketListLock);
1196
1197                 NetVscSendReceiveCompletion(Device, vmxferpagePacket->d.TransactionId);
1198
1199                 PutNetDevice(Device);
1200                 return;
1201         }
1202
1203         // Remove the 1st packet to represent the xfer page packet itself
1204         entry = REMOVE_HEAD_LIST(&listHead);
1205         xferpagePacket = CONTAINING_RECORD(entry, XFERPAGE_PACKET, ListEntry);
1206         xferpagePacket->Count = count - 1; // This is how much we can satisfy
1207         ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= vmxferpagePacket->RangeCount);
1208
1209         if (xferpagePacket->Count != vmxferpagePacket->RangeCount)
1210         {
1211                 DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket->RangeCount, xferpagePacket->Count);
1212         }
1213
1214         // Each range represents 1 RNDIS pkt that contains 1 ethernet frame
1215         for (i=0; i < (count - 1); i++)
1216         {
1217                 entry = REMOVE_HEAD_LIST(&listHead);
1218                 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1219
1220                 // Initialize the netvsc packet
1221                 netvscPacket->XferPagePacket = xferpagePacket;
1222                 netvscPacket->Completion.Recv.OnReceiveCompletion = NetVscOnReceiveCompletion;
1223                 netvscPacket->Completion.Recv.ReceiveCompletionContext = netvscPacket;
1224                 netvscPacket->Device = Device;
1225                 netvscPacket->Completion.Recv.ReceiveCompletionTid = vmxferpagePacket->d.TransactionId; // Save this so that we can send it back
1226
1227                 netvscPacket->TotalDataBufferLength = vmxferpagePacket->Ranges[i].ByteCount;
1228                 netvscPacket->PageBufferCount = 1;
1229
1230                 ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + vmxferpagePacket->Ranges[i].ByteCount < netDevice->ReceiveBufferSize);
1231
1232                 netvscPacket->PageBuffers[0].Length = vmxferpagePacket->Ranges[i].ByteCount;
1233
1234                 start = GetPhysicalAddress((void*)((unsigned long)netDevice->ReceiveBuffer + vmxferpagePacket->Ranges[i].ByteOffset));
1235
1236                 netvscPacket->PageBuffers[0].Pfn = start >> PAGE_SHIFT;
1237                 endVirtual = (unsigned long)netDevice->ReceiveBuffer
1238                     + vmxferpagePacket->Ranges[i].ByteOffset
1239                     + vmxferpagePacket->Ranges[i].ByteCount -1;
1240                 end = GetPhysicalAddress((void*)endVirtual);
1241
1242                 // Calculate the page relative offset
1243                 netvscPacket->PageBuffers[0].Offset = vmxferpagePacket->Ranges[i].ByteOffset & (PAGE_SIZE -1);
1244                 if ((end >> PAGE_SHIFT) != (start>>PAGE_SHIFT)) {
1245                     //Handle frame across multiple pages:
1246                     netvscPacket->PageBuffers[0].Length =
1247                         (netvscPacket->PageBuffers[0].Pfn <<PAGE_SHIFT) + PAGE_SIZE - start;
1248                     bytesRemain = netvscPacket->TotalDataBufferLength - netvscPacket->PageBuffers[0].Length;
1249                     for (j=1; j<NETVSC_PACKET_MAXPAGE; j++) {
1250                         netvscPacket->PageBuffers[j].Offset = 0;
1251                         if (bytesRemain <= PAGE_SIZE) {
1252                             netvscPacket->PageBuffers[j].Length = bytesRemain;
1253                             bytesRemain = 0;
1254                         } else {
1255                             netvscPacket->PageBuffers[j].Length = PAGE_SIZE;
1256                             bytesRemain -= PAGE_SIZE;
1257                         }
1258                         netvscPacket->PageBuffers[j].Pfn =
1259                             GetPhysicalAddress((void*)(endVirtual - bytesRemain)) >> PAGE_SHIFT;
1260                         netvscPacket->PageBufferCount++;
1261                         if (bytesRemain == 0)
1262                             break;
1263                     }
1264                     ASSERT(bytesRemain == 0);
1265                 }
1266                 DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1267                         i,
1268                         vmxferpagePacket->Ranges[i].ByteOffset,
1269                         vmxferpagePacket->Ranges[i].ByteCount,
1270                         netvscPacket->PageBuffers[0].Pfn,
1271                         netvscPacket->PageBuffers[0].Offset,
1272                         netvscPacket->PageBuffers[0].Length);
1273
1274                 // Pass it to the upper layer
1275                 ((NETVSC_DRIVER_OBJECT*)Device->Driver)->OnReceiveCallback(Device, netvscPacket);
1276
1277                 NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
1278         }
1279
1280         ASSERT(IsListEmpty(&listHead));
1281
1282         PutNetDevice(Device);
1283         DPRINT_EXIT(NETVSC);
1284 }
1285
1286
1287 static void
1288 NetVscSendReceiveCompletion(
1289         DEVICE_OBJECT   *Device,
1290         u64                     TransactionId
1291         )
1292 {
1293         NVSP_MESSAGE recvcompMessage;
1294         int retries=0;
1295         int ret=0;
1296
1297         DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx", TransactionId);
1298
1299         recvcompMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacketComplete;
1300
1301         // FIXME: Pass in the status
1302         recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
1303
1304 retry_send_cmplt:
1305         // Send the completion
1306         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1307                                                                                                                         &recvcompMessage,
1308                                                                                                                         sizeof(NVSP_MESSAGE),
1309                                                                                                                         TransactionId,
1310                                                                                                                         VmbusPacketTypeCompletion,
1311                                                                                                                         0);
1312         if (ret == 0) // success
1313         {
1314                 // no-op
1315         }
1316         else if (ret == -1) // no more room...wait a bit and attempt to retry 3 times
1317         {
1318                 retries++;
1319                 DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId, retries);
1320
1321                 if (retries < 4)
1322                 {
1323                         Sleep(100);
1324                         goto retry_send_cmplt;
1325                 }
1326                 else
1327                 {
1328                         DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId);
1329                 }
1330         }
1331         else
1332         {
1333                 DPRINT_ERR(NETVSC, "unable to send receive completion pkt - %llx", TransactionId);
1334         }
1335 }
1336
1337 //
1338 // Send a receive completion packet to RNDIS device (ie NetVsp)
1339 //
1340 static void
1341 NetVscOnReceiveCompletion(
1342         void * Context)
1343 {
1344         NETVSC_PACKET *packet = (NETVSC_PACKET*)Context;
1345         DEVICE_OBJECT *device = (DEVICE_OBJECT*)packet->Device;
1346         NETVSC_DEVICE* netDevice;
1347         u64     transactionId=0;
1348         bool fSendReceiveComp = FALSE;
1349
1350         DPRINT_ENTER(NETVSC);
1351
1352         ASSERT(packet->XferPagePacket);
1353
1354         // Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion,
1355         // we are using GetInboundNetDevice() since we may have disable outbound traffic already.
1356         netDevice = GetInboundNetDevice(device);
1357         if (!netDevice)
1358         {
1359                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1360                 DPRINT_EXIT(NETVSC);
1361                 return;
1362         }
1363
1364         // Overloading use of the lock.
1365         SpinlockAcquire(netDevice->ReceivePacketListLock);
1366
1367         ASSERT(packet->XferPagePacket->Count > 0);
1368         packet->XferPagePacket->Count--;
1369
1370         // Last one in the line that represent 1 xfer page packet.
1371         // Return the xfer page packet itself to the freelist
1372         if (packet->XferPagePacket->Count == 0)
1373         {
1374                 fSendReceiveComp = TRUE;
1375                 transactionId = packet->Completion.Recv.ReceiveCompletionTid;
1376
1377                 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->XferPagePacket->ListEntry);
1378         }
1379
1380         // Put the packet back
1381         INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
1382         SpinlockRelease(netDevice->ReceivePacketListLock);
1383
1384         // Send a receive completion for the xfer page packet
1385         if (fSendReceiveComp)
1386         {
1387                 NetVscSendReceiveCompletion(device, transactionId);
1388         }
1389
1390         PutNetDevice(device);
1391         DPRINT_EXIT(NETVSC);
1392 }
1393
1394
1395
1396 void
1397 NetVscOnChannelCallback(
1398         void * Context
1399         )
1400 {
1401         const int netPacketSize=2048;
1402         int ret=0;
1403         DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
1404         NETVSC_DEVICE *netDevice;
1405
1406         u32 bytesRecvd;
1407         u64 requestId;
1408         unsigned char packet[netPacketSize];
1409         VMPACKET_DESCRIPTOR *desc;
1410         unsigned char   *buffer=packet;
1411         int             bufferlen=netPacketSize;
1412
1413
1414         DPRINT_ENTER(NETVSC);
1415
1416         ASSERT(device);
1417
1418         netDevice = GetInboundNetDevice(device);
1419         if (!netDevice)
1420         {
1421                 DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring inbound packets", netDevice);
1422                 DPRINT_EXIT(NETVSC);
1423                 return;
1424         }
1425
1426         do
1427         {
1428                 ret = device->Driver->VmbusChannelInterface.RecvPacketRaw(device,
1429                                                                                                                                         buffer,
1430                                                                                                                                         bufferlen,
1431                                                                                                                                         &bytesRecvd,
1432                                                                                                                                         &requestId);
1433
1434                 if (ret == 0)
1435                 {
1436                         if (bytesRecvd > 0)
1437                         {
1438                                 DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx", bytesRecvd, requestId);
1439
1440                                 desc = (VMPACKET_DESCRIPTOR*)buffer;
1441                                 switch (desc->Type)
1442                                 {
1443                                         case VmbusPacketTypeCompletion:
1444                                                 NetVscOnSendCompletion(device, desc);
1445                                                 break;
1446
1447                                         case VmbusPacketTypeDataUsingTransferPages:
1448                                                 NetVscOnReceive(device, desc);
1449                                                 break;
1450
1451                                         default:
1452                                                 DPRINT_ERR(NETVSC, "unhandled packet type %d, tid %llx len %d\n", desc->Type, requestId, bytesRecvd);
1453                                                 break;
1454                                 }
1455
1456                                 // reset
1457                                 if (bufferlen > netPacketSize)
1458                                 {
1459                                         MemFree(buffer);
1460
1461                                         buffer = packet;
1462                                         bufferlen = netPacketSize;
1463                                 }
1464                         }
1465                         else
1466                         {
1467                                 //DPRINT_DBG(NETVSC, "nothing else to read...");
1468
1469                                 // reset
1470                                 if (bufferlen > netPacketSize)
1471                                 {
1472                                         MemFree(buffer);
1473
1474                                         buffer = packet;
1475                                         bufferlen = netPacketSize;
1476                                 }
1477
1478                                 break;
1479                         }
1480                 }
1481                 else if (ret == -2) // Handle large packet
1482                 {
1483                         buffer = MemAllocAtomic(bytesRecvd);
1484                         if (buffer == NULL)
1485                         {
1486                                 // Try again next time around
1487                                 DPRINT_ERR(NETVSC, "unable to allocate buffer of size (%d)!!", bytesRecvd);
1488                                 break;
1489                         }
1490
1491                         bufferlen = bytesRecvd;
1492                 }
1493                 else
1494                 {
1495                         ASSERT(0);
1496                 }
1497         } while (1);
1498
1499         PutNetDevice(device);
1500         DPRINT_EXIT(NETVSC);
1501         return;
1502 }