]> Pileus Git - ~andy/linux/blob - drivers/staging/hv/RndisFilter.c
Staging: hv: remove UINT32 and INT32 typedefs
[~andy/linux] / drivers / staging / hv / RndisFilter.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  *   Haiyang Zhang <haiyangz@microsoft.com>
20  *   Hank Janssen  <hjanssen@microsoft.com>
21  *
22  */
23
24 #define KERNEL_2_6_27
25
26 #include <linux/kernel.h>
27 #include "include/logging.h"
28
29 #include "include/NetVscApi.h"
30 #include "RndisFilter.h"
31
32 //
33 // Data types
34 //
35
36 typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
37         // The original driver
38         NETVSC_DRIVER_OBJECT            InnerDriver;
39
40 } RNDIS_FILTER_DRIVER_OBJECT;
41
42 typedef enum {
43         RNDIS_DEV_UNINITIALIZED = 0,
44         RNDIS_DEV_INITIALIZING,
45         RNDIS_DEV_INITIALIZED,
46         RNDIS_DEV_DATAINITIALIZED,
47 } RNDIS_DEVICE_STATE;
48
49 typedef struct _RNDIS_DEVICE {
50         NETVSC_DEVICE                   *NetDevice;
51
52         RNDIS_DEVICE_STATE              State;
53         u32                                     LinkStatus;
54         u32                                     NewRequestId;
55
56         HANDLE                                  RequestLock;
57         LIST_ENTRY                              RequestList;
58
59         UCHAR                                   HwMacAddr[HW_MACADDR_LEN];
60 } RNDIS_DEVICE;
61
62
63 typedef struct _RNDIS_REQUEST {
64         LIST_ENTRY                                      ListEntry;
65         HANDLE                                          WaitEvent;
66
67         // FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response,
68         // we can either define a max response message or add a response buffer variable above this field
69         RNDIS_MESSAGE                           ResponseMessage;
70
71         // Simplify allocation by having a netvsc packet inline
72         NETVSC_PACKET                           Packet;
73         PAGE_BUFFER                                     Buffer;
74         // FIXME: We assumed a fixed size request here.
75         RNDIS_MESSAGE                           RequestMessage;
76 } RNDIS_REQUEST;
77
78
79 typedef struct _RNDIS_FILTER_PACKET {
80         void                                            *CompletionContext;
81         PFN_ON_SENDRECVCOMPLETION       OnCompletion;
82
83         RNDIS_MESSAGE                           Message;
84 } RNDIS_FILTER_PACKET;
85
86 //
87 // Internal routines
88 //
89 static int
90 RndisFilterSendRequest(
91         RNDIS_DEVICE    *Device,
92         RNDIS_REQUEST   *Request
93         );
94
95 static void
96 RndisFilterReceiveResponse(
97         RNDIS_DEVICE    *Device,
98         RNDIS_MESSAGE   *Response
99         );
100
101 static void
102 RndisFilterReceiveIndicateStatus(
103         RNDIS_DEVICE    *Device,
104         RNDIS_MESSAGE   *Response
105         );
106
107 static void
108 RndisFilterReceiveData(
109         RNDIS_DEVICE    *Device,
110         RNDIS_MESSAGE   *Message,
111         NETVSC_PACKET   *Packet
112         );
113
114 static int
115 RndisFilterOnReceive(
116         DEVICE_OBJECT           *Device,
117         NETVSC_PACKET           *Packet
118         );
119
120 static int
121 RndisFilterQueryDevice(
122         RNDIS_DEVICE    *Device,
123         u32                     Oid,
124         void                    *Result,
125         u32                     *ResultSize
126         );
127
128 static inline int
129 RndisFilterQueryDeviceMac(
130         RNDIS_DEVICE    *Device
131         );
132
133 static inline int
134 RndisFilterQueryDeviceLinkStatus(
135         RNDIS_DEVICE    *Device
136         );
137
138 static int
139 RndisFilterSetPacketFilter(
140         RNDIS_DEVICE    *Device,
141         u32                     NewFilter
142         );
143
144 static int
145 RndisFilterInitDevice(
146         RNDIS_DEVICE            *Device
147         );
148
149 static int
150 RndisFilterOpenDevice(
151         RNDIS_DEVICE            *Device
152         );
153
154 static int
155 RndisFilterCloseDevice(
156         RNDIS_DEVICE            *Device
157         );
158
159 static int
160 RndisFilterOnDeviceAdd(
161         DEVICE_OBJECT   *Device,
162         void                    *AdditionalInfo
163         );
164
165 static int
166 RndisFilterOnDeviceRemove(
167         DEVICE_OBJECT *Device
168         );
169
170 static void
171 RndisFilterOnCleanup(
172         DRIVER_OBJECT *Driver
173         );
174
175 static int
176 RndisFilterOnOpen(
177         DEVICE_OBJECT           *Device
178         );
179
180 static int
181 RndisFilterOnClose(
182         DEVICE_OBJECT           *Device
183         );
184
185 static int
186 RndisFilterOnSend(
187         DEVICE_OBJECT           *Device,
188         NETVSC_PACKET           *Packet
189         );
190
191 static void
192 RndisFilterOnSendCompletion(
193    void *Context
194         );
195
196 static void
197 RndisFilterOnSendRequestCompletion(
198    void *Context
199         );
200
201 //
202 // Global var
203 //
204
205 // The one and only
206 RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
207
208 static inline RNDIS_DEVICE* GetRndisDevice(void)
209 {
210         RNDIS_DEVICE *device;
211
212         device = MemAllocZeroed(sizeof(RNDIS_DEVICE));
213         if (!device)
214         {
215                 return NULL;
216         }
217
218         device->RequestLock = SpinlockCreate();
219         if (!device->RequestLock)
220         {
221                 MemFree(device);
222                 return NULL;
223         }
224
225         INITIALIZE_LIST_HEAD(&device->RequestList);
226
227         device->State = RNDIS_DEV_UNINITIALIZED;
228
229         return device;
230 }
231
232 static inline void PutRndisDevice(RNDIS_DEVICE *Device)
233 {
234         SpinlockClose(Device->RequestLock);
235         MemFree(Device);
236 }
237
238 static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, u32 MessageType, u32 MessageLength)
239 {
240         RNDIS_REQUEST *request;
241         RNDIS_MESSAGE *rndisMessage;
242         RNDIS_SET_REQUEST *set;
243
244         request = MemAllocZeroed(sizeof(RNDIS_REQUEST));
245         if (!request)
246         {
247                 return NULL;
248         }
249
250         request->WaitEvent = WaitEventCreate();
251         if (!request->WaitEvent)
252         {
253                 MemFree(request);
254                 return NULL;
255         }
256
257         rndisMessage = &request->RequestMessage;
258         rndisMessage->NdisMessageType = MessageType;
259         rndisMessage->MessageLength = MessageLength;
260
261         // Set the request id. This field is always after the rndis header for request/response packet types so
262         // we just used the SetRequest as a template
263         set = &rndisMessage->Message.SetRequest;
264         set->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
265
266         // Add to the request list
267         SpinlockAcquire(Device->RequestLock);
268         INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
269         SpinlockRelease(Device->RequestLock);
270
271         return request;
272 }
273
274 static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
275 {
276         SpinlockAcquire(Device->RequestLock);
277         REMOVE_ENTRY_LIST(&Request->ListEntry);
278         SpinlockRelease(Device->RequestLock);
279
280         WaitEventClose(Request->WaitEvent);
281         MemFree(Request);
282 }
283
284 static inline void DumpRndisMessage(RNDIS_MESSAGE *RndisMessage)
285 {
286         switch (RndisMessage->NdisMessageType)
287         {
288         case REMOTE_NDIS_PACKET_MSG:
289                 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",
290                         RndisMessage->MessageLength,
291                         RndisMessage->Message.Packet.DataOffset,
292                         RndisMessage->Message.Packet.DataLength,
293                         RndisMessage->Message.Packet.NumOOBDataElements,
294                         RndisMessage->Message.Packet.OOBDataOffset,
295                         RndisMessage->Message.Packet.OOBDataLength,
296                         RndisMessage->Message.Packet.PerPacketInfoOffset,
297                         RndisMessage->Message.Packet.PerPacketInfoLength);
298                 break;
299
300         case REMOTE_NDIS_INITIALIZE_CMPLT:
301                 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)",
302                         RndisMessage->MessageLength,
303                         RndisMessage->Message.InitializeComplete.RequestId,
304                         RndisMessage->Message.InitializeComplete.Status,
305                         RndisMessage->Message.InitializeComplete.MajorVersion,
306                         RndisMessage->Message.InitializeComplete.MinorVersion,
307                         RndisMessage->Message.InitializeComplete.DeviceFlags,
308                         RndisMessage->Message.InitializeComplete.MaxTransferSize,
309                         RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
310                         RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
311                 break;
312
313         case REMOTE_NDIS_QUERY_CMPLT:
314                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT (len %u, id 0x%x, status 0x%x, buf len %u, buf offset %u)",
315                         RndisMessage->MessageLength,
316                         RndisMessage->Message.QueryComplete.RequestId,
317                         RndisMessage->Message.QueryComplete.Status,
318                         RndisMessage->Message.QueryComplete.InformationBufferLength,
319                         RndisMessage->Message.QueryComplete.InformationBufferOffset);
320                 break;
321
322         case REMOTE_NDIS_SET_CMPLT:
323                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
324                         RndisMessage->MessageLength,
325                         RndisMessage->Message.SetComplete.RequestId,
326                         RndisMessage->Message.SetComplete.Status);
327                 break;
328
329         case REMOTE_NDIS_INDICATE_STATUS_MSG:
330                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG (len %u, status 0x%x, buf len %u, buf offset %u)",
331                         RndisMessage->MessageLength,
332                         RndisMessage->Message.IndicateStatus.Status,
333                         RndisMessage->Message.IndicateStatus.StatusBufferLength,
334                         RndisMessage->Message.IndicateStatus.StatusBufferOffset);
335                 break;
336
337         default:
338                 DPRINT_DBG(NETVSC, "0x%x (len %u)",
339                         RndisMessage->NdisMessageType,
340                         RndisMessage->MessageLength);
341                 break;
342         }
343 }
344
345 static int
346 RndisFilterSendRequest(
347         RNDIS_DEVICE    *Device,
348         RNDIS_REQUEST   *Request
349         )
350 {
351         int ret=0;
352         NETVSC_PACKET *packet;
353
354         DPRINT_ENTER(NETVSC);
355
356         // Setup the packet to send it
357         packet = &Request->Packet;
358
359         packet->IsDataPacket = FALSE;
360         packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
361         packet->PageBufferCount = 1;
362
363         packet->PageBuffers[0].Pfn = GetPhysicalAddress(&Request->RequestMessage) >> PAGE_SHIFT;
364         packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
365         packet->PageBuffers[0].Offset = (ULONG_PTR)&Request->RequestMessage & (PAGE_SIZE -1);
366
367         packet->Completion.Send.SendCompletionContext = Request;//packet;
368         packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
369         packet->Completion.Send.SendCompletionTid = (ULONG_PTR)Device;
370
371         ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
372         DPRINT_EXIT(NETVSC);
373         return ret;
374 }
375
376
377 static void
378 RndisFilterReceiveResponse(
379         RNDIS_DEVICE    *Device,
380         RNDIS_MESSAGE   *Response
381         )
382 {
383         LIST_ENTRY *anchor;
384         LIST_ENTRY *curr;
385         RNDIS_REQUEST *request=NULL;
386         BOOL found=FALSE;
387
388         DPRINT_ENTER(NETVSC);
389
390         SpinlockAcquire(Device->RequestLock);
391         ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList)
392         {
393                 request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
394
395                 // All request/response message contains RequestId as the 1st field
396                 if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
397                 {
398                         DPRINT_DBG(NETVSC, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
399                                 request->RequestMessage.Message.InitializeRequest.RequestId, request->RequestMessage.NdisMessageType, Response->NdisMessageType);
400
401                         found = TRUE;
402                         break;
403                 }
404         }
405         SpinlockRelease(Device->RequestLock);
406
407         if (found)
408         {
409                 if (Response->MessageLength <= sizeof(RNDIS_MESSAGE))
410                 {
411                         memcpy(&request->ResponseMessage, Response, Response->MessageLength);
412                 }
413                 else
414                 {
415                         DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %u)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
416
417                         if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) // does not have a request id field
418                         {
419                                 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
420                         }
421                         else
422                         {
423                                 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
424                         }
425                 }
426
427                 WaitEventSet(request->WaitEvent);
428         }
429         else
430         {
431                 DPRINT_ERR(NETVSC, "no rndis request found for this response (id 0x%x res type 0x%x)",
432                                 Response->Message.InitializeComplete.RequestId, Response->NdisMessageType);
433         }
434
435         DPRINT_EXIT(NETVSC);
436 }
437
438 static void
439 RndisFilterReceiveIndicateStatus(
440         RNDIS_DEVICE    *Device,
441         RNDIS_MESSAGE   *Response
442         )
443 {
444         RNDIS_INDICATE_STATUS *indicate = &Response->Message.IndicateStatus;
445
446         if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT)
447         {
448                 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
449         }
450         else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT)
451         {
452                 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
453         }
454         else
455         {
456                 // TODO:
457         }
458 }
459
460 static void
461 RndisFilterReceiveData(
462         RNDIS_DEVICE    *Device,
463         RNDIS_MESSAGE   *Message,
464         NETVSC_PACKET   *Packet
465         )
466 {
467         RNDIS_PACKET *rndisPacket;
468         u32 dataOffset;
469
470         DPRINT_ENTER(NETVSC);
471
472         // empty ethernet frame ??
473         ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(RNDIS_PACKET));
474
475         rndisPacket = &Message->Message.Packet;
476
477         // FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
478         // netvsc packet (ie TotalDataBufferLength != MessageLength)
479
480         // Remove the rndis header and pass it back up the stack
481         dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
482
483         Packet->TotalDataBufferLength -= dataOffset;
484         Packet->PageBuffers[0].Offset += dataOffset;
485         Packet->PageBuffers[0].Length -= dataOffset;
486
487         Packet->IsDataPacket = TRUE;
488
489         gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device, Packet);
490
491         DPRINT_EXIT(NETVSC);
492 }
493
494 static int
495 RndisFilterOnReceive(
496         DEVICE_OBJECT           *Device,
497         NETVSC_PACKET           *Packet
498         )
499 {
500         NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
501         RNDIS_DEVICE *rndisDevice;
502         RNDIS_MESSAGE rndisMessage;
503         RNDIS_MESSAGE *rndisHeader;
504
505         DPRINT_ENTER(NETVSC);
506
507         ASSERT(netDevice);
508         //Make sure the rndis device state is initialized
509         if (!netDevice->Extension)
510         {
511                 DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
512                 DPRINT_EXIT(NETVSC);
513                 return -1;
514         }
515
516         rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
517         if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED)
518         {
519                 DPRINT_ERR(NETVSC, "got rndis message but rndis device uninitialized...dropping this message!");
520                 DPRINT_EXIT(NETVSC);
521                 return -1;
522         }
523
524         rndisHeader = (RNDIS_MESSAGE*)PageMapVirtualAddress(Packet->PageBuffers[0].Pfn);
525
526         rndisHeader = (void*)((ULONG_PTR)rndisHeader + Packet->PageBuffers[0].Offset);
527
528         // Make sure we got a valid rndis message
529         // FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but
530         // the ByteCount field in the xfer page range shows 52 bytes
531 #if 0
532         if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
533         {
534                 PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
535
536                 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
537                         rndisHeader->MessageLength, Packet->TotalDataBufferLength);
538                 DPRINT_EXIT(NETVSC);
539                 return -1;
540         }
541 #endif
542
543         if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE)))
544         {
545                 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %u)...marking it an error!",
546                         rndisHeader->MessageLength, sizeof(RNDIS_MESSAGE));
547         }
548
549         memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE))?sizeof(RNDIS_MESSAGE):rndisHeader->MessageLength);
550
551         PageUnmapVirtualAddress((void*)(ULONG_PTR)rndisHeader - Packet->PageBuffers[0].Offset);
552
553         DumpRndisMessage(&rndisMessage);
554
555         switch (rndisMessage.NdisMessageType)
556         {
557                 // data msg
558         case REMOTE_NDIS_PACKET_MSG:
559                 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
560                 break;
561
562                 // completion msgs
563         case REMOTE_NDIS_INITIALIZE_CMPLT:
564         case REMOTE_NDIS_QUERY_CMPLT:
565         case REMOTE_NDIS_SET_CMPLT:
566         //case REMOTE_NDIS_RESET_CMPLT:
567         //case REMOTE_NDIS_KEEPALIVE_CMPLT:
568                 RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
569                 break;
570
571                 // notification msgs
572         case REMOTE_NDIS_INDICATE_STATUS_MSG:
573                 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
574                 break;
575         default:
576                 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", rndisMessage.NdisMessageType, rndisMessage.MessageLength);
577                 break;
578         }
579
580         DPRINT_EXIT(NETVSC);
581         return 0;
582 }
583
584
585 static int
586 RndisFilterQueryDevice(
587         RNDIS_DEVICE    *Device,
588         u32                     Oid,
589         void                    *Result,
590         u32                     *ResultSize
591         )
592 {
593         RNDIS_REQUEST *request;
594         u32 inresultSize = *ResultSize;
595         RNDIS_QUERY_REQUEST *query;
596         RNDIS_QUERY_COMPLETE *queryComplete;
597         int ret=0;
598
599         DPRINT_ENTER(NETVSC);
600
601         ASSERT(Result);
602
603         *ResultSize = 0;
604         request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST));
605         if (!request)
606         {
607                 ret = -1;
608                 goto Cleanup;
609         }
610
611         // Setup the rndis query
612         query = &request->RequestMessage.Message.QueryRequest;
613         query->Oid = Oid;
614         query->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
615         query->InformationBufferLength = 0;
616         query->DeviceVcHandle = 0;
617
618         ret = RndisFilterSendRequest(Device, request);
619         if (ret != 0)
620         {
621                 goto Cleanup;
622         }
623
624         WaitEventWait(request->WaitEvent);
625
626         // Copy the response back
627         queryComplete = &request->ResponseMessage.Message.QueryComplete;
628
629         if (queryComplete->InformationBufferLength > inresultSize)
630         {
631                 ret = -1;
632                 goto Cleanup;
633         }
634
635         memcpy(Result,
636                         (void*)((ULONG_PTR)queryComplete + queryComplete->InformationBufferOffset),
637                         queryComplete->InformationBufferLength);
638
639         *ResultSize = queryComplete->InformationBufferLength;
640
641 Cleanup:
642         if (request)
643         {
644                 PutRndisRequest(Device, request);
645         }
646         DPRINT_EXIT(NETVSC);
647
648         return ret;
649 }
650
651 static inline int
652 RndisFilterQueryDeviceMac(
653         RNDIS_DEVICE    *Device
654         )
655 {
656         u32 size=HW_MACADDR_LEN;
657
658         return RndisFilterQueryDevice(Device,
659                                                                         RNDIS_OID_802_3_PERMANENT_ADDRESS,
660                                                                         Device->HwMacAddr,
661                                                                         &size);
662 }
663
664 static inline int
665 RndisFilterQueryDeviceLinkStatus(
666         RNDIS_DEVICE    *Device
667         )
668 {
669         u32 size=sizeof(u32);
670
671         return RndisFilterQueryDevice(Device,
672                                                                         RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
673                                                                         &Device->LinkStatus,
674                                                                         &size);
675 }
676
677 static int
678 RndisFilterSetPacketFilter(
679         RNDIS_DEVICE    *Device,
680         u32                     NewFilter
681         )
682 {
683         RNDIS_REQUEST *request;
684         RNDIS_SET_REQUEST *set;
685         RNDIS_SET_COMPLETE *setComplete;
686         u32 status;
687         int ret;
688
689         DPRINT_ENTER(NETVSC);
690
691         ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(u32) <= sizeof(RNDIS_MESSAGE));
692
693         request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(u32));
694         if (!request)
695         {
696                 ret = -1;
697                 goto Cleanup;
698         }
699
700         // Setup the rndis set
701         set = &request->RequestMessage.Message.SetRequest;
702         set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
703         set->InformationBufferLength = sizeof(u32);
704         set->InformationBufferOffset = sizeof(RNDIS_SET_REQUEST);
705
706         memcpy((void*)(ULONG_PTR)set + sizeof(RNDIS_SET_REQUEST), &NewFilter, sizeof(u32));
707
708         ret = RndisFilterSendRequest(Device, request);
709         if (ret != 0)
710         {
711                 goto Cleanup;
712         }
713
714         ret = WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
715         if (!ret)
716         {
717                 ret = -1;
718                 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
719                 // We cant deallocate the request since we may still receive a send completion for it.
720                 goto Exit;
721         }
722         else
723         {
724                 if (ret > 0)
725                 {
726                         ret = 0;
727                 }
728                 setComplete = &request->ResponseMessage.Message.SetComplete;
729                 status = setComplete->Status;
730         }
731
732 Cleanup:
733         if (request)
734         {
735                 PutRndisRequest(Device, request);
736         }
737 Exit:
738         DPRINT_EXIT(NETVSC);
739
740         return ret;
741 }
742
743 int
744 RndisFilterInit(
745         NETVSC_DRIVER_OBJECT    *Driver
746         )
747 {
748         DPRINT_ENTER(NETVSC);
749
750         DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET));
751
752         Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
753         Driver->AdditionalRequestPageBufferCount = 1; // For rndis header
754
755         //Driver->Context = rndisDriver;
756
757         memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
758
759         /*rndisDriver->Driver = Driver;
760
761         ASSERT(Driver->OnLinkStatusChanged);
762         rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
763
764         // Save the original dispatch handlers before we override it
765         gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
766         gRndisFilter.InnerDriver.Base.OnDeviceRemove = Driver->Base.OnDeviceRemove;
767         gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
768
769         ASSERT(Driver->OnSend);
770         ASSERT(Driver->OnReceiveCallback);
771         gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
772         gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
773         gRndisFilter.InnerDriver.OnLinkStatusChanged = Driver->OnLinkStatusChanged;
774
775         // Override
776         Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
777         Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
778         Driver->Base.OnCleanup = RndisFilterOnCleanup;
779         Driver->OnSend = RndisFilterOnSend;
780         Driver->OnOpen = RndisFilterOnOpen;
781         Driver->OnClose = RndisFilterOnClose;
782         //Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus;
783         Driver->OnReceiveCallback = RndisFilterOnReceive;
784
785         DPRINT_EXIT(NETVSC);
786
787         return 0;
788 }
789
790 static int
791 RndisFilterInitDevice(
792         RNDIS_DEVICE    *Device
793         )
794 {
795         RNDIS_REQUEST *request;
796         RNDIS_INITIALIZE_REQUEST *init;
797         RNDIS_INITIALIZE_COMPLETE *initComplete;
798         u32 status;
799         int ret;
800
801         DPRINT_ENTER(NETVSC);
802
803         request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST));
804         if (!request)
805         {
806                 ret = -1;
807                 goto Cleanup;
808         }
809
810         // Setup the rndis set
811         init = &request->RequestMessage.Message.InitializeRequest;
812         init->MajorVersion = RNDIS_MAJOR_VERSION;
813         init->MinorVersion = RNDIS_MINOR_VERSION;
814         init->MaxTransferSize = 2048; // FIXME: Use 1536 - rounded ethernet frame size
815
816         Device->State = RNDIS_DEV_INITIALIZING;
817
818         ret = RndisFilterSendRequest(Device, request);
819         if (ret != 0)
820         {
821                 Device->State = RNDIS_DEV_UNINITIALIZED;
822                 goto Cleanup;
823         }
824
825         WaitEventWait(request->WaitEvent);
826
827         initComplete = &request->ResponseMessage.Message.InitializeComplete;
828         status = initComplete->Status;
829         if (status == RNDIS_STATUS_SUCCESS)
830         {
831                 Device->State = RNDIS_DEV_INITIALIZED;
832                 ret = 0;
833         }
834         else
835         {
836                 Device->State = RNDIS_DEV_UNINITIALIZED;
837                 ret = -1;
838         }
839
840 Cleanup:
841         if (request)
842         {
843                 PutRndisRequest(Device, request);
844         }
845         DPRINT_EXIT(NETVSC);
846
847         return ret;
848 }
849
850 static void
851 RndisFilterHaltDevice(
852         RNDIS_DEVICE    *Device
853         )
854 {
855         RNDIS_REQUEST *request;
856         RNDIS_HALT_REQUEST *halt;
857
858         DPRINT_ENTER(NETVSC);
859
860         // Attempt to do a rndis device halt
861         request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST));
862         if (!request)
863         {
864                 goto Cleanup;
865         }
866
867         // Setup the rndis set
868         halt = &request->RequestMessage.Message.HaltRequest;
869         halt->RequestId = InterlockedIncrement((int*)&Device->NewRequestId);
870
871         // Ignore return since this msg is optional.
872         RndisFilterSendRequest(Device, request);
873
874         Device->State = RNDIS_DEV_UNINITIALIZED;
875
876 Cleanup:
877         if (request)
878         {
879                 PutRndisRequest(Device, request);
880         }
881         DPRINT_EXIT(NETVSC);
882         return;
883 }
884
885
886 static int
887 RndisFilterOpenDevice(
888         RNDIS_DEVICE    *Device
889         )
890 {
891         int ret=0;
892
893         DPRINT_ENTER(NETVSC);
894
895         if (Device->State != RNDIS_DEV_INITIALIZED)
896                 return 0;
897
898         ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
899         if (ret == 0)
900         {
901                 Device->State = RNDIS_DEV_DATAINITIALIZED;
902         }
903
904         DPRINT_EXIT(NETVSC);
905         return ret;
906 }
907
908 static int
909 RndisFilterCloseDevice(
910         RNDIS_DEVICE            *Device
911         )
912 {
913         int ret;
914
915         DPRINT_ENTER(NETVSC);
916
917         if (Device->State != RNDIS_DEV_DATAINITIALIZED)
918                 return 0;
919
920         ret = RndisFilterSetPacketFilter(Device, 0);
921         if (ret == 0)
922         {
923                 Device->State = RNDIS_DEV_INITIALIZED;
924         }
925
926         DPRINT_EXIT(NETVSC);
927
928         return ret;
929 }
930
931
932 int
933 RndisFilterOnDeviceAdd(
934         DEVICE_OBJECT   *Device,
935         void                    *AdditionalInfo
936         )
937 {
938         int ret;
939         NETVSC_DEVICE *netDevice;
940         RNDIS_DEVICE *rndisDevice;
941         NETVSC_DEVICE_INFO *deviceInfo = (NETVSC_DEVICE_INFO*)AdditionalInfo;
942
943         DPRINT_ENTER(NETVSC);
944
945         //rndisDevice = MemAlloc(sizeof(RNDIS_DEVICE));
946         rndisDevice = GetRndisDevice();
947         if (!rndisDevice)
948         {
949                 DPRINT_EXIT(NETVSC);
950                 return -1;
951         }
952
953         DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
954
955         // Let the inner driver handle this first to create the netvsc channel
956         // NOTE! Once the channel is created, we may get a receive callback
957         // (RndisFilterOnReceive()) before this call is completed
958         ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
959         if (ret != 0)
960         {
961                 PutRndisDevice(rndisDevice);
962                 DPRINT_EXIT(NETVSC);
963                 return ret;
964         }
965
966         //
967         // Initialize the rndis device
968         //
969         netDevice = (NETVSC_DEVICE*)Device->Extension;
970         ASSERT(netDevice);
971         ASSERT(netDevice->Device);
972
973         netDevice->Extension = rndisDevice;
974         rndisDevice->NetDevice = netDevice;
975
976         // Send the rndis initialization message
977         ret = RndisFilterInitDevice(rndisDevice);
978         if (ret != 0)
979         {
980                 // TODO: If rndis init failed, we will need to shut down the channel
981         }
982
983         // Get the mac address
984         ret = RndisFilterQueryDeviceMac(rndisDevice);
985         if (ret != 0)
986         {
987                 // TODO: shutdown rndis device and the channel
988         }
989
990         DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
991                                 rndisDevice,
992                                 rndisDevice->HwMacAddr[0],
993                                 rndisDevice->HwMacAddr[1],
994                                 rndisDevice->HwMacAddr[2],
995                                 rndisDevice->HwMacAddr[3],
996                                 rndisDevice->HwMacAddr[4],
997                                 rndisDevice->HwMacAddr[5]);
998
999         memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
1000
1001         RndisFilterQueryDeviceLinkStatus(rndisDevice);
1002
1003         deviceInfo->LinkState = rndisDevice->LinkStatus;
1004         DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, ((deviceInfo->LinkState)?("down"):("up")));
1005
1006         DPRINT_EXIT(NETVSC);
1007
1008         return ret;
1009 }
1010
1011
1012 static int
1013 RndisFilterOnDeviceRemove(
1014         DEVICE_OBJECT *Device
1015         )
1016 {
1017         NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
1018         RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
1019
1020         DPRINT_ENTER(NETVSC);
1021
1022         // Halt and release the rndis device
1023         RndisFilterHaltDevice(rndisDevice);
1024
1025         PutRndisDevice(rndisDevice);
1026         netDevice->Extension = NULL;
1027
1028         // Pass control to inner driver to remove the device
1029         gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
1030
1031         DPRINT_EXIT(NETVSC);
1032
1033         return 0;
1034 }
1035
1036
1037 static void
1038 RndisFilterOnCleanup(
1039         DRIVER_OBJECT *Driver
1040         )
1041 {
1042         DPRINT_ENTER(NETVSC);
1043
1044         DPRINT_EXIT(NETVSC);
1045 }
1046
1047 static int
1048 RndisFilterOnOpen(
1049         DEVICE_OBJECT           *Device
1050         )
1051 {
1052         int ret;
1053         NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
1054
1055         DPRINT_ENTER(NETVSC);
1056
1057         ASSERT(netDevice);
1058         ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
1059
1060         DPRINT_EXIT(NETVSC);
1061
1062         return ret;
1063 }
1064
1065 static int
1066 RndisFilterOnClose(
1067         DEVICE_OBJECT           *Device
1068         )
1069 {
1070         int ret;
1071         NETVSC_DEVICE *netDevice = (NETVSC_DEVICE*)Device->Extension;
1072
1073         DPRINT_ENTER(NETVSC);
1074
1075         ASSERT(netDevice);
1076         ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
1077
1078         DPRINT_EXIT(NETVSC);
1079
1080         return ret;
1081 }
1082
1083
1084 static int
1085 RndisFilterOnSend(
1086         DEVICE_OBJECT           *Device,
1087         NETVSC_PACKET           *Packet
1088         )
1089 {
1090         int ret=0;
1091         RNDIS_FILTER_PACKET *filterPacket;
1092         RNDIS_MESSAGE *rndisMessage;
1093         RNDIS_PACKET *rndisPacket;
1094         u32 rndisMessageSize;
1095
1096         DPRINT_ENTER(NETVSC);
1097
1098         // Add the rndis header
1099         filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
1100         ASSERT(filterPacket);
1101
1102         memset(filterPacket, 0, sizeof(RNDIS_FILTER_PACKET));
1103
1104         rndisMessage = &filterPacket->Message;
1105         rndisMessageSize = RNDIS_MESSAGE_SIZE(RNDIS_PACKET);
1106
1107         rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
1108         rndisMessage->MessageLength = Packet->TotalDataBufferLength + rndisMessageSize;
1109
1110         rndisPacket = &rndisMessage->Message.Packet;
1111         rndisPacket->DataOffset = sizeof(RNDIS_PACKET);
1112         rndisPacket->DataLength = Packet->TotalDataBufferLength;
1113
1114         Packet->IsDataPacket = TRUE;
1115         Packet->PageBuffers[0].Pfn              = GetPhysicalAddress(rndisMessage) >> PAGE_SHIFT;
1116         Packet->PageBuffers[0].Offset   = (ULONG_PTR)rndisMessage & (PAGE_SIZE-1);
1117         Packet->PageBuffers[0].Length   = rndisMessageSize;
1118
1119         // Save the packet send completion and context
1120         filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
1121         filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
1122
1123         // Use ours
1124         Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
1125         Packet->Completion.Send.SendCompletionContext = filterPacket;
1126
1127         ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
1128         if (ret != 0)
1129         {
1130                 // Reset the completion to originals to allow retries from above
1131                 Packet->Completion.Send.OnSendCompletion = filterPacket->OnCompletion;
1132                 Packet->Completion.Send.SendCompletionContext = filterPacket->CompletionContext;
1133         }
1134
1135         DPRINT_EXIT(NETVSC);
1136
1137         return ret;
1138 }
1139
1140 static void
1141 RndisFilterOnSendCompletion(
1142    void *Context)
1143 {
1144         RNDIS_FILTER_PACKET *filterPacket = (RNDIS_FILTER_PACKET *)Context;
1145
1146         DPRINT_ENTER(NETVSC);
1147
1148         // Pass it back to the original handler
1149         filterPacket->OnCompletion(filterPacket->CompletionContext);
1150
1151         DPRINT_EXIT(NETVSC);
1152 }
1153
1154
1155 static void
1156 RndisFilterOnSendRequestCompletion(
1157    void *Context
1158    )
1159 {
1160         DPRINT_ENTER(NETVSC);
1161
1162         // Noop
1163         DPRINT_EXIT(NETVSC);
1164 }