]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blob - drivers/staging/hv/rndis_filter.c
6640682d36b7310325b36867d57dad570584954a
[lisovros/linux_canprio.git] / drivers / staging / hv / rndis_filter.c
1 /*
2  * Copyright (c) 2009, Microsoft Corporation.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15  * Place - Suite 330, Boston, MA 02111-1307 USA.
16  *
17  * Authors:
18  *   Haiyang Zhang <haiyangz@microsoft.com>
19  *   Hank Janssen  <hjanssen@microsoft.com>
20  */
21 #include <linux/kernel.h>
22 #include <linux/highmem.h>
23 #include <linux/slab.h>
24 #include <linux/io.h>
25 #include <linux/if_ether.h>
26
27 #include "osd.h"
28 #include "logging.h"
29 #include "netvsc_api.h"
30 #include "rndis_filter.h"
31
32 /* Data types */
33 struct rndis_filter_driver_object {
34         /* The original driver */
35         struct netvsc_driver InnerDriver;
36 };
37
38 enum rndis_device_state {
39         RNDIS_DEV_UNINITIALIZED = 0,
40         RNDIS_DEV_INITIALIZING,
41         RNDIS_DEV_INITIALIZED,
42         RNDIS_DEV_DATAINITIALIZED,
43 };
44
45 struct rndis_device {
46         struct netvsc_device *NetDevice;
47
48         enum rndis_device_state State;
49         u32 LinkStatus;
50         atomic_t NewRequestId;
51
52         spinlock_t request_lock;
53         struct list_head RequestList;
54
55         unsigned char HwMacAddr[ETH_ALEN];
56 };
57
58 struct rndis_request {
59         struct list_head ListEntry;
60         struct osd_waitevent *WaitEvent;
61
62         /*
63          * FIXME: We assumed a fixed size response here. If we do ever need to
64          * handle a bigger response, we can either define a max response
65          * message or add a response buffer variable above this field
66          */
67         struct rndis_message ResponseMessage;
68
69         /* Simplify allocation by having a netvsc packet inline */
70         struct hv_netvsc_packet Packet;
71         struct hv_page_buffer Buffer;
72         /* FIXME: We assumed a fixed size request here. */
73         struct rndis_message RequestMessage;
74 };
75
76
77 struct rndis_filter_packet {
78         void *CompletionContext;
79         void (*OnCompletion)(void *context);
80         struct rndis_message Message;
81 };
82
83
84 static int RndisFilterOnDeviceAdd(struct hv_device *Device,
85                                   void *AdditionalInfo);
86
87 static int RndisFilterOnDeviceRemove(struct hv_device *Device);
88
89 static void RndisFilterOnCleanup(struct hv_driver *Driver);
90
91 static int RndisFilterOnSend(struct hv_device *Device,
92                              struct hv_netvsc_packet *Packet);
93
94 static void RndisFilterOnSendCompletion(void *Context);
95
96 static void RndisFilterOnSendRequestCompletion(void *Context);
97
98
99 /* The one and only */
100 static struct rndis_filter_driver_object gRndisFilter;
101
102 static struct rndis_device *GetRndisDevice(void)
103 {
104         struct rndis_device *device;
105
106         device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
107         if (!device)
108                 return NULL;
109
110         spin_lock_init(&device->request_lock);
111
112         INIT_LIST_HEAD(&device->RequestList);
113
114         device->State = RNDIS_DEV_UNINITIALIZED;
115
116         return device;
117 }
118
119 static struct rndis_request *GetRndisRequest(struct rndis_device *Device,
120                                              u32 MessageType,
121                                              u32 MessageLength)
122 {
123         struct rndis_request *request;
124         struct rndis_message *rndisMessage;
125         struct rndis_set_request *set;
126         unsigned long flags;
127
128         request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
129         if (!request)
130                 return NULL;
131
132         request->WaitEvent = osd_WaitEventCreate();
133         if (!request->WaitEvent) {
134                 kfree(request);
135                 return NULL;
136         }
137
138         rndisMessage = &request->RequestMessage;
139         rndisMessage->NdisMessageType = MessageType;
140         rndisMessage->MessageLength = MessageLength;
141
142         /*
143          * Set the request id. This field is always after the rndis header for
144          * request/response packet types so we just used the SetRequest as a
145          * template
146          */
147         set = &rndisMessage->Message.SetRequest;
148         set->RequestId = atomic_inc_return(&Device->NewRequestId);
149
150         /* Add to the request list */
151         spin_lock_irqsave(&Device->request_lock, flags);
152         list_add_tail(&request->ListEntry, &Device->RequestList);
153         spin_unlock_irqrestore(&Device->request_lock, flags);
154
155         return request;
156 }
157
158 static void PutRndisRequest(struct rndis_device *Device,
159                             struct rndis_request *Request)
160 {
161         unsigned long flags;
162
163         spin_lock_irqsave(&Device->request_lock, flags);
164         list_del(&Request->ListEntry);
165         spin_unlock_irqrestore(&Device->request_lock, flags);
166
167         kfree(Request->WaitEvent);
168         kfree(Request);
169 }
170
171 static void DumpRndisMessage(struct rndis_message *RndisMessage)
172 {
173         switch (RndisMessage->NdisMessageType) {
174         case REMOTE_NDIS_PACKET_MSG:
175                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
176                            "data offset %u data len %u, # oob %u, "
177                            "oob offset %u, oob len %u, pkt offset %u, "
178                            "pkt len %u",
179                            RndisMessage->MessageLength,
180                            RndisMessage->Message.Packet.DataOffset,
181                            RndisMessage->Message.Packet.DataLength,
182                            RndisMessage->Message.Packet.NumOOBDataElements,
183                            RndisMessage->Message.Packet.OOBDataOffset,
184                            RndisMessage->Message.Packet.OOBDataLength,
185                            RndisMessage->Message.Packet.PerPacketInfoOffset,
186                            RndisMessage->Message.Packet.PerPacketInfoLength);
187                 break;
188
189         case REMOTE_NDIS_INITIALIZE_CMPLT:
190                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
191                         "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
192                         "device flags %d, max xfer size 0x%x, max pkts %u, "
193                         "pkt aligned %u)",
194                         RndisMessage->MessageLength,
195                         RndisMessage->Message.InitializeComplete.RequestId,
196                         RndisMessage->Message.InitializeComplete.Status,
197                         RndisMessage->Message.InitializeComplete.MajorVersion,
198                         RndisMessage->Message.InitializeComplete.MinorVersion,
199                         RndisMessage->Message.InitializeComplete.DeviceFlags,
200                         RndisMessage->Message.InitializeComplete.MaxTransferSize,
201                         RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
202                         RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
203                 break;
204
205         case REMOTE_NDIS_QUERY_CMPLT:
206                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
207                         "(len %u, id 0x%x, status 0x%x, buf len %u, "
208                         "buf offset %u)",
209                         RndisMessage->MessageLength,
210                         RndisMessage->Message.QueryComplete.RequestId,
211                         RndisMessage->Message.QueryComplete.Status,
212                         RndisMessage->Message.QueryComplete.InformationBufferLength,
213                         RndisMessage->Message.QueryComplete.InformationBufferOffset);
214                 break;
215
216         case REMOTE_NDIS_SET_CMPLT:
217                 DPRINT_DBG(NETVSC,
218                         "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
219                         RndisMessage->MessageLength,
220                         RndisMessage->Message.SetComplete.RequestId,
221                         RndisMessage->Message.SetComplete.Status);
222                 break;
223
224         case REMOTE_NDIS_INDICATE_STATUS_MSG:
225                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
226                         "(len %u, status 0x%x, buf len %u, buf offset %u)",
227                         RndisMessage->MessageLength,
228                         RndisMessage->Message.IndicateStatus.Status,
229                         RndisMessage->Message.IndicateStatus.StatusBufferLength,
230                         RndisMessage->Message.IndicateStatus.StatusBufferOffset);
231                 break;
232
233         default:
234                 DPRINT_DBG(NETVSC, "0x%x (len %u)",
235                         RndisMessage->NdisMessageType,
236                         RndisMessage->MessageLength);
237                 break;
238         }
239 }
240
241 static int RndisFilterSendRequest(struct rndis_device *Device,
242                                   struct rndis_request *Request)
243 {
244         int ret;
245         struct hv_netvsc_packet *packet;
246
247         /* Setup the packet to send it */
248         packet = &Request->Packet;
249
250         packet->IsDataPacket = false;
251         packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
252         packet->PageBufferCount = 1;
253
254         packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >>
255                                         PAGE_SHIFT;
256         packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
257         packet->PageBuffers[0].Offset =
258                 (unsigned long)&Request->RequestMessage & (PAGE_SIZE - 1);
259
260         packet->Completion.Send.SendCompletionContext = Request;/* packet; */
261         packet->Completion.Send.OnSendCompletion =
262                 RndisFilterOnSendRequestCompletion;
263         packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
264
265         ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
266         DPRINT_EXIT(NETVSC);
267         return ret;
268 }
269
270 static void RndisFilterReceiveResponse(struct rndis_device *Device,
271                                        struct rndis_message *Response)
272 {
273         struct rndis_request *request = NULL;
274         bool found = false;
275         unsigned long flags;
276
277         spin_lock_irqsave(&Device->request_lock, flags);
278         list_for_each_entry(request, &Device->RequestList, ListEntry) {
279                 /*
280                  * All request/response message contains RequestId as the 1st
281                  * field
282                  */
283                 if (request->RequestMessage.Message.InitializeRequest.RequestId
284                     == Response->Message.InitializeComplete.RequestId) {
285                         DPRINT_DBG(NETVSC, "found rndis request for "
286                                 "this response (id 0x%x req type 0x%x res "
287                                 "type 0x%x)",
288                                 request->RequestMessage.Message.InitializeRequest.RequestId,
289                                 request->RequestMessage.NdisMessageType,
290                                 Response->NdisMessageType);
291
292                         found = true;
293                         break;
294                 }
295         }
296         spin_unlock_irqrestore(&Device->request_lock, flags);
297
298         if (found) {
299                 if (Response->MessageLength <= sizeof(struct rndis_message)) {
300                         memcpy(&request->ResponseMessage, Response,
301                                Response->MessageLength);
302                 } else {
303                         DPRINT_ERR(NETVSC, "rndis response buffer overflow "
304                                   "detected (size %u max %zu)",
305                                   Response->MessageLength,
306                                   sizeof(struct rndis_filter_packet));
307
308                         if (Response->NdisMessageType ==
309                             REMOTE_NDIS_RESET_CMPLT) {
310                                 /* does not have a request id field */
311                                 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
312                         } else {
313                                 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
314                         }
315                 }
316
317                 osd_WaitEventSet(request->WaitEvent);
318         } else {
319                 DPRINT_ERR(NETVSC, "no rndis request found for this response "
320                            "(id 0x%x res type 0x%x)",
321                            Response->Message.InitializeComplete.RequestId,
322                            Response->NdisMessageType);
323         }
324
325         DPRINT_EXIT(NETVSC);
326 }
327
328 static void RndisFilterReceiveIndicateStatus(struct rndis_device *Device,
329                                              struct rndis_message *Response)
330 {
331         struct rndis_indicate_status *indicate =
332                         &Response->Message.IndicateStatus;
333
334         if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT) {
335                 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
336         } else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT) {
337                 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
338         } else {
339                 /*
340                  * TODO:
341                  */
342         }
343 }
344
345 static void RndisFilterReceiveData(struct rndis_device *Device,
346                                    struct rndis_message *Message,
347                                    struct hv_netvsc_packet *Packet)
348 {
349         struct rndis_packet *rndisPacket;
350         u32 dataOffset;
351
352         /* empty ethernet frame ?? */
353         /* ASSERT(Packet->PageBuffers[0].Length > */
354         /*      RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
355
356         rndisPacket = &Message->Message.Packet;
357
358         /*
359          * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
360          * netvsc packet (ie TotalDataBufferLength != MessageLength)
361          */
362
363         /* Remove the rndis header and pass it back up the stack */
364         dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
365
366         Packet->TotalDataBufferLength -= dataOffset;
367         Packet->PageBuffers[0].Offset += dataOffset;
368         Packet->PageBuffers[0].Length -= dataOffset;
369
370         Packet->IsDataPacket = true;
371
372         gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device,
373                                                    Packet);
374
375         DPRINT_EXIT(NETVSC);
376 }
377
378 static int RndisFilterOnReceive(struct hv_device *Device,
379                                 struct hv_netvsc_packet *Packet)
380 {
381         struct netvsc_device *netDevice = Device->Extension;
382         struct rndis_device *rndisDevice;
383         struct rndis_message rndisMessage;
384         struct rndis_message *rndisHeader;
385
386         if (!netDevice)
387                 return -EINVAL;
388
389         /* Make sure the rndis device state is initialized */
390         if (!netDevice->Extension) {
391                 DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
392                           "dropping this message!");
393                 DPRINT_EXIT(NETVSC);
394                 return -1;
395         }
396
397         rndisDevice = (struct rndis_device *)netDevice->Extension;
398         if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED) {
399                 DPRINT_ERR(NETVSC, "got rndis message but rndis device "
400                            "uninitialized...dropping this message!");
401                 DPRINT_EXIT(NETVSC);
402                 return -1;
403         }
404
405         rndisHeader = (struct rndis_message *)kmap_atomic(
406                         pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
407
408         rndisHeader = (void *)((unsigned long)rndisHeader +
409                         Packet->PageBuffers[0].Offset);
410
411         /* Make sure we got a valid rndis message */
412         /*
413          * FIXME: There seems to be a bug in set completion msg where its
414          * MessageLength is 16 bytes but the ByteCount field in the xfer page
415          * range shows 52 bytes
416          * */
417 #if 0
418         if (Packet->TotalDataBufferLength != rndisHeader->MessageLength) {
419                 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset,
420                               KM_IRQ0);
421
422                 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
423                            "bytes got %u)...dropping this message!",
424                            rndisHeader->MessageLength,
425                            Packet->TotalDataBufferLength);
426                 DPRINT_EXIT(NETVSC);
427                 return -1;
428         }
429 #endif
430
431         if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) &&
432             (rndisHeader->MessageLength > sizeof(struct rndis_message))) {
433                 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow "
434                            "detected (got %u, max %zu)...marking it an error!",
435                            rndisHeader->MessageLength,
436                            sizeof(struct rndis_message));
437         }
438
439         memcpy(&rndisMessage, rndisHeader,
440                 (rndisHeader->MessageLength > sizeof(struct rndis_message)) ?
441                         sizeof(struct rndis_message) :
442                         rndisHeader->MessageLength);
443
444         kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
445
446         DumpRndisMessage(&rndisMessage);
447
448         switch (rndisMessage.NdisMessageType) {
449         case REMOTE_NDIS_PACKET_MSG:
450                 /* data msg */
451                 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
452                 break;
453
454         case REMOTE_NDIS_INITIALIZE_CMPLT:
455         case REMOTE_NDIS_QUERY_CMPLT:
456         case REMOTE_NDIS_SET_CMPLT:
457         /* case REMOTE_NDIS_RESET_CMPLT: */
458         /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
459                 /* completion msgs */
460                 RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
461                 break;
462
463         case REMOTE_NDIS_INDICATE_STATUS_MSG:
464                 /* notification msgs */
465                 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
466                 break;
467         default:
468                 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)",
469                            rndisMessage.NdisMessageType,
470                            rndisMessage.MessageLength);
471                 break;
472         }
473
474         DPRINT_EXIT(NETVSC);
475         return 0;
476 }
477
478 static int RndisFilterQueryDevice(struct rndis_device *Device, u32 Oid,
479                                   void *Result, u32 *ResultSize)
480 {
481         struct rndis_request *request;
482         u32 inresultSize = *ResultSize;
483         struct rndis_query_request *query;
484         struct rndis_query_complete *queryComplete;
485         int ret = 0;
486
487         if (!Result)
488                 return -EINVAL;
489
490         *ResultSize = 0;
491         request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG,
492                         RNDIS_MESSAGE_SIZE(struct rndis_query_request));
493         if (!request) {
494                 ret = -1;
495                 goto Cleanup;
496         }
497
498         /* Setup the rndis query */
499         query = &request->RequestMessage.Message.QueryRequest;
500         query->Oid = Oid;
501         query->InformationBufferOffset = sizeof(struct rndis_query_request);
502         query->InformationBufferLength = 0;
503         query->DeviceVcHandle = 0;
504
505         ret = RndisFilterSendRequest(Device, request);
506         if (ret != 0)
507                 goto Cleanup;
508
509         osd_WaitEventWait(request->WaitEvent);
510
511         /* Copy the response back */
512         queryComplete = &request->ResponseMessage.Message.QueryComplete;
513
514         if (queryComplete->InformationBufferLength > inresultSize) {
515                 ret = -1;
516                 goto Cleanup;
517         }
518
519         memcpy(Result,
520                (void *)((unsigned long)queryComplete +
521                          queryComplete->InformationBufferOffset),
522                queryComplete->InformationBufferLength);
523
524         *ResultSize = queryComplete->InformationBufferLength;
525
526 Cleanup:
527         if (request)
528                 PutRndisRequest(Device, request);
529         DPRINT_EXIT(NETVSC);
530
531         return ret;
532 }
533
534 static int RndisFilterQueryDeviceMac(struct rndis_device *Device)
535 {
536         u32 size = ETH_ALEN;
537
538         return RndisFilterQueryDevice(Device,
539                                       RNDIS_OID_802_3_PERMANENT_ADDRESS,
540                                       Device->HwMacAddr, &size);
541 }
542
543 static int RndisFilterQueryDeviceLinkStatus(struct rndis_device *Device)
544 {
545         u32 size = sizeof(u32);
546
547         return RndisFilterQueryDevice(Device,
548                                       RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
549                                       &Device->LinkStatus, &size);
550 }
551
552 static int RndisFilterSetPacketFilter(struct rndis_device *Device,
553                                       u32 NewFilter)
554 {
555         struct rndis_request *request;
556         struct rndis_set_request *set;
557         struct rndis_set_complete *setComplete;
558         u32 status;
559         int ret;
560
561         /* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
562         /*      sizeof(struct rndis_message)); */
563
564         request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG,
565                         RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
566                         sizeof(u32));
567         if (!request) {
568                 ret = -1;
569                 goto Cleanup;
570         }
571
572         /* Setup the rndis set */
573         set = &request->RequestMessage.Message.SetRequest;
574         set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
575         set->InformationBufferLength = sizeof(u32);
576         set->InformationBufferOffset = sizeof(struct rndis_set_request);
577
578         memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
579                &NewFilter, sizeof(u32));
580
581         ret = RndisFilterSendRequest(Device, request);
582         if (ret != 0)
583                 goto Cleanup;
584
585         ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
586         if (!ret) {
587                 ret = -1;
588                 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
589                 /*
590                  * We cant deallocate the request since we may still receive a
591                  * send completion for it.
592                  */
593                 goto Exit;
594         } else {
595                 if (ret > 0)
596                         ret = 0;
597                 setComplete = &request->ResponseMessage.Message.SetComplete;
598                 status = setComplete->Status;
599         }
600
601 Cleanup:
602         if (request)
603                 PutRndisRequest(Device, request);
604 Exit:
605         DPRINT_EXIT(NETVSC);
606
607         return ret;
608 }
609
610 int RndisFilterInit(struct netvsc_driver *Driver)
611 {
612         DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd",
613                    sizeof(struct rndis_filter_packet));
614
615         Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
616
617         /* Driver->Context = rndisDriver; */
618
619         memset(&gRndisFilter, 0, sizeof(struct rndis_filter_driver_object));
620
621         /*rndisDriver->Driver = Driver;
622
623         ASSERT(Driver->OnLinkStatusChanged);
624         rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
625
626         /* Save the original dispatch handlers before we override it */
627         gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
628         gRndisFilter.InnerDriver.Base.OnDeviceRemove =
629                                         Driver->Base.OnDeviceRemove;
630         gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
631
632         /* ASSERT(Driver->OnSend); */
633         /* ASSERT(Driver->OnReceiveCallback); */
634         gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
635         gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
636         gRndisFilter.InnerDriver.OnLinkStatusChanged =
637                                         Driver->OnLinkStatusChanged;
638
639         /* Override */
640         Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
641         Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
642         Driver->Base.OnCleanup = RndisFilterOnCleanup;
643         Driver->OnSend = RndisFilterOnSend;
644         /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
645         Driver->OnReceiveCallback = RndisFilterOnReceive;
646
647         DPRINT_EXIT(NETVSC);
648
649         return 0;
650 }
651
652 static int RndisFilterInitDevice(struct rndis_device *Device)
653 {
654         struct rndis_request *request;
655         struct rndis_initialize_request *init;
656         struct rndis_initialize_complete *initComplete;
657         u32 status;
658         int ret;
659
660         request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG,
661                         RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
662         if (!request) {
663                 ret = -1;
664                 goto Cleanup;
665         }
666
667         /* Setup the rndis set */
668         init = &request->RequestMessage.Message.InitializeRequest;
669         init->MajorVersion = RNDIS_MAJOR_VERSION;
670         init->MinorVersion = RNDIS_MINOR_VERSION;
671         /* FIXME: Use 1536 - rounded ethernet frame size */
672         init->MaxTransferSize = 2048;
673
674         Device->State = RNDIS_DEV_INITIALIZING;
675
676         ret = RndisFilterSendRequest(Device, request);
677         if (ret != 0) {
678                 Device->State = RNDIS_DEV_UNINITIALIZED;
679                 goto Cleanup;
680         }
681
682         osd_WaitEventWait(request->WaitEvent);
683
684         initComplete = &request->ResponseMessage.Message.InitializeComplete;
685         status = initComplete->Status;
686         if (status == RNDIS_STATUS_SUCCESS) {
687                 Device->State = RNDIS_DEV_INITIALIZED;
688                 ret = 0;
689         } else {
690                 Device->State = RNDIS_DEV_UNINITIALIZED;
691                 ret = -1;
692         }
693
694 Cleanup:
695         if (request)
696                 PutRndisRequest(Device, request);
697         DPRINT_EXIT(NETVSC);
698
699         return ret;
700 }
701
702 static void RndisFilterHaltDevice(struct rndis_device *Device)
703 {
704         struct rndis_request *request;
705         struct rndis_halt_request *halt;
706
707         /* Attempt to do a rndis device halt */
708         request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG,
709                                 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
710         if (!request)
711                 goto Cleanup;
712
713         /* Setup the rndis set */
714         halt = &request->RequestMessage.Message.HaltRequest;
715         halt->RequestId = atomic_inc_return(&Device->NewRequestId);
716
717         /* Ignore return since this msg is optional. */
718         RndisFilterSendRequest(Device, request);
719
720         Device->State = RNDIS_DEV_UNINITIALIZED;
721
722 Cleanup:
723         if (request)
724                 PutRndisRequest(Device, request);
725         DPRINT_EXIT(NETVSC);
726         return;
727 }
728
729 static int RndisFilterOpenDevice(struct rndis_device *Device)
730 {
731         int ret;
732
733         if (Device->State != RNDIS_DEV_INITIALIZED)
734                 return 0;
735
736         ret = RndisFilterSetPacketFilter(Device,
737                                          NDIS_PACKET_TYPE_BROADCAST |
738                                          NDIS_PACKET_TYPE_ALL_MULTICAST |
739                                          NDIS_PACKET_TYPE_DIRECTED);
740         if (ret == 0)
741                 Device->State = RNDIS_DEV_DATAINITIALIZED;
742
743         DPRINT_EXIT(NETVSC);
744         return ret;
745 }
746
747 static int RndisFilterCloseDevice(struct rndis_device *Device)
748 {
749         int ret;
750
751         if (Device->State != RNDIS_DEV_DATAINITIALIZED)
752                 return 0;
753
754         ret = RndisFilterSetPacketFilter(Device, 0);
755         if (ret == 0)
756                 Device->State = RNDIS_DEV_INITIALIZED;
757
758         DPRINT_EXIT(NETVSC);
759
760         return ret;
761 }
762
763 static int RndisFilterOnDeviceAdd(struct hv_device *Device,
764                                   void *AdditionalInfo)
765 {
766         int ret;
767         struct netvsc_device *netDevice;
768         struct rndis_device *rndisDevice;
769         struct netvsc_device_info *deviceInfo = AdditionalInfo;
770
771         rndisDevice = GetRndisDevice();
772         if (!rndisDevice) {
773                 DPRINT_EXIT(NETVSC);
774                 return -1;
775         }
776
777         DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
778
779         /*
780          * Let the inner driver handle this first to create the netvsc channel
781          * NOTE! Once the channel is created, we may get a receive callback
782          * (RndisFilterOnReceive()) before this call is completed
783          */
784         ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
785         if (ret != 0) {
786                 kfree(rndisDevice);
787                 DPRINT_EXIT(NETVSC);
788                 return ret;
789         }
790
791
792         /* Initialize the rndis device */
793         netDevice = Device->Extension;
794         /* ASSERT(netDevice); */
795         /* ASSERT(netDevice->Device); */
796
797         netDevice->Extension = rndisDevice;
798         rndisDevice->NetDevice = netDevice;
799
800         /* Send the rndis initialization message */
801         ret = RndisFilterInitDevice(rndisDevice);
802         if (ret != 0) {
803                 /*
804                  * TODO: If rndis init failed, we will need to shut down the
805                  * channel
806                  */
807         }
808
809         /* Get the mac address */
810         ret = RndisFilterQueryDeviceMac(rndisDevice);
811         if (ret != 0) {
812                 /*
813                  * TODO: shutdown rndis device and the channel
814                  */
815         }
816
817         DPRINT_INFO(NETVSC, "Device 0x%p mac addr %pM",
818                     rndisDevice, rndisDevice->HwMacAddr);
819
820         memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, ETH_ALEN);
821
822         RndisFilterQueryDeviceLinkStatus(rndisDevice);
823
824         deviceInfo->LinkState = rndisDevice->LinkStatus;
825         DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice,
826                     ((deviceInfo->LinkState) ? ("down") : ("up")));
827
828         DPRINT_EXIT(NETVSC);
829
830         return ret;
831 }
832
833 static int RndisFilterOnDeviceRemove(struct hv_device *Device)
834 {
835         struct netvsc_device *netDevice = Device->Extension;
836         struct rndis_device *rndisDevice = netDevice->Extension;
837
838         /* Halt and release the rndis device */
839         RndisFilterHaltDevice(rndisDevice);
840
841         kfree(rndisDevice);
842         netDevice->Extension = NULL;
843
844         /* Pass control to inner driver to remove the device */
845         gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
846
847         DPRINT_EXIT(NETVSC);
848
849         return 0;
850 }
851
852 static void RndisFilterOnCleanup(struct hv_driver *Driver)
853 {
854         DPRINT_EXIT(NETVSC);
855 }
856
857 int RndisFilterOnOpen(struct hv_device *Device)
858 {
859         int ret;
860         struct netvsc_device *netDevice = Device->Extension;
861
862         if (!netDevice)
863                 return -EINVAL;
864
865         ret = RndisFilterOpenDevice(netDevice->Extension);
866
867         DPRINT_EXIT(NETVSC);
868
869         return ret;
870 }
871
872 int RndisFilterOnClose(struct hv_device *Device)
873 {
874         int ret;
875         struct netvsc_device *netDevice = Device->Extension;
876
877         if (!netDevice)
878                 return -EINVAL;
879
880         ret = RndisFilterCloseDevice(netDevice->Extension);
881
882         DPRINT_EXIT(NETVSC);
883
884         return ret;
885 }
886
887 static int RndisFilterOnSend(struct hv_device *Device,
888                              struct hv_netvsc_packet *Packet)
889 {
890         int ret;
891         struct rndis_filter_packet *filterPacket;
892         struct rndis_message *rndisMessage;
893         struct rndis_packet *rndisPacket;
894         u32 rndisMessageSize;
895
896         /* Add the rndis header */
897         filterPacket = (struct rndis_filter_packet *)Packet->Extension;
898         /* ASSERT(filterPacket); */
899
900         memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
901
902         rndisMessage = &filterPacket->Message;
903         rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
904
905         rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
906         rndisMessage->MessageLength = Packet->TotalDataBufferLength +
907                                       rndisMessageSize;
908
909         rndisPacket = &rndisMessage->Message.Packet;
910         rndisPacket->DataOffset = sizeof(struct rndis_packet);
911         rndisPacket->DataLength = Packet->TotalDataBufferLength;
912
913         Packet->IsDataPacket = true;
914         Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
915         Packet->PageBuffers[0].Offset =
916                         (unsigned long)rndisMessage & (PAGE_SIZE-1);
917         Packet->PageBuffers[0].Length = rndisMessageSize;
918
919         /* Save the packet send completion and context */
920         filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
921         filterPacket->CompletionContext =
922                                 Packet->Completion.Send.SendCompletionContext;
923
924         /* Use ours */
925         Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
926         Packet->Completion.Send.SendCompletionContext = filterPacket;
927
928         ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
929         if (ret != 0) {
930                 /*
931                  * Reset the completion to originals to allow retries from
932                  * above
933                  */
934                 Packet->Completion.Send.OnSendCompletion =
935                                 filterPacket->OnCompletion;
936                 Packet->Completion.Send.SendCompletionContext =
937                                 filterPacket->CompletionContext;
938         }
939
940         DPRINT_EXIT(NETVSC);
941
942         return ret;
943 }
944
945 static void RndisFilterOnSendCompletion(void *Context)
946 {
947         struct rndis_filter_packet *filterPacket = Context;
948
949         /* Pass it back to the original handler */
950         filterPacket->OnCompletion(filterPacket->CompletionContext);
951
952         DPRINT_EXIT(NETVSC);
953 }
954
955
956 static void RndisFilterOnSendRequestCompletion(void *Context)
957 {
958         /* Noop */
959         DPRINT_EXIT(NETVSC);
960 }