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