]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/hv/rndis_filter.c
Merge git://git.infradead.org/battery-2.6
[karo-tx-linux.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         return ret;
267 }
268
269 static void RndisFilterReceiveResponse(struct rndis_device *Device,
270                                        struct rndis_message *Response)
271 {
272         struct rndis_request *request = NULL;
273         bool found = false;
274         unsigned long flags;
275
276         spin_lock_irqsave(&Device->request_lock, flags);
277         list_for_each_entry(request, &Device->RequestList, ListEntry) {
278                 /*
279                  * All request/response message contains RequestId as the 1st
280                  * field
281                  */
282                 if (request->RequestMessage.Message.InitializeRequest.RequestId
283                     == Response->Message.InitializeComplete.RequestId) {
284                         DPRINT_DBG(NETVSC, "found rndis request for "
285                                 "this response (id 0x%x req type 0x%x res "
286                                 "type 0x%x)",
287                                 request->RequestMessage.Message.InitializeRequest.RequestId,
288                                 request->RequestMessage.NdisMessageType,
289                                 Response->NdisMessageType);
290
291                         found = true;
292                         break;
293                 }
294         }
295         spin_unlock_irqrestore(&Device->request_lock, flags);
296
297         if (found) {
298                 if (Response->MessageLength <= sizeof(struct rndis_message)) {
299                         memcpy(&request->ResponseMessage, Response,
300                                Response->MessageLength);
301                 } else {
302                         DPRINT_ERR(NETVSC, "rndis response buffer overflow "
303                                   "detected (size %u max %zu)",
304                                   Response->MessageLength,
305                                   sizeof(struct rndis_filter_packet));
306
307                         if (Response->NdisMessageType ==
308                             REMOTE_NDIS_RESET_CMPLT) {
309                                 /* does not have a request id field */
310                                 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
311                         } else {
312                                 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
313                         }
314                 }
315
316                 osd_WaitEventSet(request->WaitEvent);
317         } else {
318                 DPRINT_ERR(NETVSC, "no rndis request found for this response "
319                            "(id 0x%x res type 0x%x)",
320                            Response->Message.InitializeComplete.RequestId,
321                            Response->NdisMessageType);
322         }
323 }
324
325 static void RndisFilterReceiveIndicateStatus(struct rndis_device *Device,
326                                              struct rndis_message *Response)
327 {
328         struct rndis_indicate_status *indicate =
329                         &Response->Message.IndicateStatus;
330
331         if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT) {
332                 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
333         } else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT) {
334                 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
335         } else {
336                 /*
337                  * TODO:
338                  */
339         }
340 }
341
342 static void RndisFilterReceiveData(struct rndis_device *Device,
343                                    struct rndis_message *Message,
344                                    struct hv_netvsc_packet *Packet)
345 {
346         struct rndis_packet *rndisPacket;
347         u32 dataOffset;
348
349         /* empty ethernet frame ?? */
350         /* ASSERT(Packet->PageBuffers[0].Length > */
351         /*      RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
352
353         rndisPacket = &Message->Message.Packet;
354
355         /*
356          * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
357          * netvsc packet (ie TotalDataBufferLength != MessageLength)
358          */
359
360         /* Remove the rndis header and pass it back up the stack */
361         dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
362
363         Packet->TotalDataBufferLength -= dataOffset;
364         Packet->PageBuffers[0].Offset += dataOffset;
365         Packet->PageBuffers[0].Length -= dataOffset;
366
367         Packet->IsDataPacket = true;
368
369         gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device,
370                                                    Packet);
371 }
372
373 static int RndisFilterOnReceive(struct hv_device *Device,
374                                 struct hv_netvsc_packet *Packet)
375 {
376         struct netvsc_device *netDevice = Device->Extension;
377         struct rndis_device *rndisDevice;
378         struct rndis_message rndisMessage;
379         struct rndis_message *rndisHeader;
380
381         if (!netDevice)
382                 return -EINVAL;
383
384         /* Make sure the rndis device state is initialized */
385         if (!netDevice->Extension) {
386                 DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
387                           "dropping this message!");
388                 return -1;
389         }
390
391         rndisDevice = (struct rndis_device *)netDevice->Extension;
392         if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED) {
393                 DPRINT_ERR(NETVSC, "got rndis message but rndis device "
394                            "uninitialized...dropping this message!");
395                 return -1;
396         }
397
398         rndisHeader = (struct rndis_message *)kmap_atomic(
399                         pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
400
401         rndisHeader = (void *)((unsigned long)rndisHeader +
402                         Packet->PageBuffers[0].Offset);
403
404         /* Make sure we got a valid rndis message */
405         /*
406          * FIXME: There seems to be a bug in set completion msg where its
407          * MessageLength is 16 bytes but the ByteCount field in the xfer page
408          * range shows 52 bytes
409          * */
410 #if 0
411         if (Packet->TotalDataBufferLength != rndisHeader->MessageLength) {
412                 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset,
413                               KM_IRQ0);
414
415                 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
416                            "bytes got %u)...dropping this message!",
417                            rndisHeader->MessageLength,
418                            Packet->TotalDataBufferLength);
419                 return -1;
420         }
421 #endif
422
423         if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) &&
424             (rndisHeader->MessageLength > sizeof(struct rndis_message))) {
425                 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow "
426                            "detected (got %u, max %zu)...marking it an error!",
427                            rndisHeader->MessageLength,
428                            sizeof(struct rndis_message));
429         }
430
431         memcpy(&rndisMessage, rndisHeader,
432                 (rndisHeader->MessageLength > sizeof(struct rndis_message)) ?
433                         sizeof(struct rndis_message) :
434                         rndisHeader->MessageLength);
435
436         kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
437
438         DumpRndisMessage(&rndisMessage);
439
440         switch (rndisMessage.NdisMessageType) {
441         case REMOTE_NDIS_PACKET_MSG:
442                 /* data msg */
443                 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
444                 break;
445
446         case REMOTE_NDIS_INITIALIZE_CMPLT:
447         case REMOTE_NDIS_QUERY_CMPLT:
448         case REMOTE_NDIS_SET_CMPLT:
449         /* case REMOTE_NDIS_RESET_CMPLT: */
450         /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
451                 /* completion msgs */
452                 RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
453                 break;
454
455         case REMOTE_NDIS_INDICATE_STATUS_MSG:
456                 /* notification msgs */
457                 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
458                 break;
459         default:
460                 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)",
461                            rndisMessage.NdisMessageType,
462                            rndisMessage.MessageLength);
463                 break;
464         }
465
466         return 0;
467 }
468
469 static int RndisFilterQueryDevice(struct rndis_device *Device, u32 Oid,
470                                   void *Result, u32 *ResultSize)
471 {
472         struct rndis_request *request;
473         u32 inresultSize = *ResultSize;
474         struct rndis_query_request *query;
475         struct rndis_query_complete *queryComplete;
476         int ret = 0;
477
478         if (!Result)
479                 return -EINVAL;
480
481         *ResultSize = 0;
482         request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG,
483                         RNDIS_MESSAGE_SIZE(struct rndis_query_request));
484         if (!request) {
485                 ret = -1;
486                 goto Cleanup;
487         }
488
489         /* Setup the rndis query */
490         query = &request->RequestMessage.Message.QueryRequest;
491         query->Oid = Oid;
492         query->InformationBufferOffset = sizeof(struct rndis_query_request);
493         query->InformationBufferLength = 0;
494         query->DeviceVcHandle = 0;
495
496         ret = RndisFilterSendRequest(Device, request);
497         if (ret != 0)
498                 goto Cleanup;
499
500         osd_WaitEventWait(request->WaitEvent);
501
502         /* Copy the response back */
503         queryComplete = &request->ResponseMessage.Message.QueryComplete;
504
505         if (queryComplete->InformationBufferLength > inresultSize) {
506                 ret = -1;
507                 goto Cleanup;
508         }
509
510         memcpy(Result,
511                (void *)((unsigned long)queryComplete +
512                          queryComplete->InformationBufferOffset),
513                queryComplete->InformationBufferLength);
514
515         *ResultSize = queryComplete->InformationBufferLength;
516
517 Cleanup:
518         if (request)
519                 PutRndisRequest(Device, request);
520
521         return ret;
522 }
523
524 static int RndisFilterQueryDeviceMac(struct rndis_device *Device)
525 {
526         u32 size = ETH_ALEN;
527
528         return RndisFilterQueryDevice(Device,
529                                       RNDIS_OID_802_3_PERMANENT_ADDRESS,
530                                       Device->HwMacAddr, &size);
531 }
532
533 static int RndisFilterQueryDeviceLinkStatus(struct rndis_device *Device)
534 {
535         u32 size = sizeof(u32);
536
537         return RndisFilterQueryDevice(Device,
538                                       RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
539                                       &Device->LinkStatus, &size);
540 }
541
542 static int RndisFilterSetPacketFilter(struct rndis_device *Device,
543                                       u32 NewFilter)
544 {
545         struct rndis_request *request;
546         struct rndis_set_request *set;
547         struct rndis_set_complete *setComplete;
548         u32 status;
549         int ret;
550
551         /* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
552         /*      sizeof(struct rndis_message)); */
553
554         request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG,
555                         RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
556                         sizeof(u32));
557         if (!request) {
558                 ret = -1;
559                 goto Cleanup;
560         }
561
562         /* Setup the rndis set */
563         set = &request->RequestMessage.Message.SetRequest;
564         set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
565         set->InformationBufferLength = sizeof(u32);
566         set->InformationBufferOffset = sizeof(struct rndis_set_request);
567
568         memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
569                &NewFilter, sizeof(u32));
570
571         ret = RndisFilterSendRequest(Device, request);
572         if (ret != 0)
573                 goto Cleanup;
574
575         ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
576         if (!ret) {
577                 ret = -1;
578                 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
579                 /*
580                  * We cant deallocate the request since we may still receive a
581                  * send completion for it.
582                  */
583                 goto Exit;
584         } else {
585                 if (ret > 0)
586                         ret = 0;
587                 setComplete = &request->ResponseMessage.Message.SetComplete;
588                 status = setComplete->Status;
589         }
590
591 Cleanup:
592         if (request)
593                 PutRndisRequest(Device, request);
594 Exit:
595         return ret;
596 }
597
598 int RndisFilterInit(struct netvsc_driver *Driver)
599 {
600         DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd",
601                    sizeof(struct rndis_filter_packet));
602
603         Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
604
605         /* Driver->Context = rndisDriver; */
606
607         memset(&gRndisFilter, 0, sizeof(struct rndis_filter_driver_object));
608
609         /*rndisDriver->Driver = Driver;
610
611         ASSERT(Driver->OnLinkStatusChanged);
612         rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
613
614         /* Save the original dispatch handlers before we override it */
615         gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
616         gRndisFilter.InnerDriver.Base.OnDeviceRemove =
617                                         Driver->Base.OnDeviceRemove;
618         gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
619
620         /* ASSERT(Driver->OnSend); */
621         /* ASSERT(Driver->OnReceiveCallback); */
622         gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
623         gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
624         gRndisFilter.InnerDriver.OnLinkStatusChanged =
625                                         Driver->OnLinkStatusChanged;
626
627         /* Override */
628         Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
629         Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
630         Driver->Base.OnCleanup = RndisFilterOnCleanup;
631         Driver->OnSend = RndisFilterOnSend;
632         /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
633         Driver->OnReceiveCallback = RndisFilterOnReceive;
634
635         return 0;
636 }
637
638 static int RndisFilterInitDevice(struct rndis_device *Device)
639 {
640         struct rndis_request *request;
641         struct rndis_initialize_request *init;
642         struct rndis_initialize_complete *initComplete;
643         u32 status;
644         int ret;
645
646         request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG,
647                         RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
648         if (!request) {
649                 ret = -1;
650                 goto Cleanup;
651         }
652
653         /* Setup the rndis set */
654         init = &request->RequestMessage.Message.InitializeRequest;
655         init->MajorVersion = RNDIS_MAJOR_VERSION;
656         init->MinorVersion = RNDIS_MINOR_VERSION;
657         /* FIXME: Use 1536 - rounded ethernet frame size */
658         init->MaxTransferSize = 2048;
659
660         Device->State = RNDIS_DEV_INITIALIZING;
661
662         ret = RndisFilterSendRequest(Device, request);
663         if (ret != 0) {
664                 Device->State = RNDIS_DEV_UNINITIALIZED;
665                 goto Cleanup;
666         }
667
668         osd_WaitEventWait(request->WaitEvent);
669
670         initComplete = &request->ResponseMessage.Message.InitializeComplete;
671         status = initComplete->Status;
672         if (status == RNDIS_STATUS_SUCCESS) {
673                 Device->State = RNDIS_DEV_INITIALIZED;
674                 ret = 0;
675         } else {
676                 Device->State = RNDIS_DEV_UNINITIALIZED;
677                 ret = -1;
678         }
679
680 Cleanup:
681         if (request)
682                 PutRndisRequest(Device, request);
683
684         return ret;
685 }
686
687 static void RndisFilterHaltDevice(struct rndis_device *Device)
688 {
689         struct rndis_request *request;
690         struct rndis_halt_request *halt;
691
692         /* Attempt to do a rndis device halt */
693         request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG,
694                                 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
695         if (!request)
696                 goto Cleanup;
697
698         /* Setup the rndis set */
699         halt = &request->RequestMessage.Message.HaltRequest;
700         halt->RequestId = atomic_inc_return(&Device->NewRequestId);
701
702         /* Ignore return since this msg is optional. */
703         RndisFilterSendRequest(Device, request);
704
705         Device->State = RNDIS_DEV_UNINITIALIZED;
706
707 Cleanup:
708         if (request)
709                 PutRndisRequest(Device, request);
710         return;
711 }
712
713 static int RndisFilterOpenDevice(struct rndis_device *Device)
714 {
715         int ret;
716
717         if (Device->State != RNDIS_DEV_INITIALIZED)
718                 return 0;
719
720         ret = RndisFilterSetPacketFilter(Device,
721                                          NDIS_PACKET_TYPE_BROADCAST |
722                                          NDIS_PACKET_TYPE_ALL_MULTICAST |
723                                          NDIS_PACKET_TYPE_DIRECTED);
724         if (ret == 0)
725                 Device->State = RNDIS_DEV_DATAINITIALIZED;
726
727         return ret;
728 }
729
730 static int RndisFilterCloseDevice(struct rndis_device *Device)
731 {
732         int ret;
733
734         if (Device->State != RNDIS_DEV_DATAINITIALIZED)
735                 return 0;
736
737         ret = RndisFilterSetPacketFilter(Device, 0);
738         if (ret == 0)
739                 Device->State = RNDIS_DEV_INITIALIZED;
740
741         return ret;
742 }
743
744 static int RndisFilterOnDeviceAdd(struct hv_device *Device,
745                                   void *AdditionalInfo)
746 {
747         int ret;
748         struct netvsc_device *netDevice;
749         struct rndis_device *rndisDevice;
750         struct netvsc_device_info *deviceInfo = AdditionalInfo;
751
752         rndisDevice = GetRndisDevice();
753         if (!rndisDevice)
754                 return -1;
755
756         DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
757
758         /*
759          * Let the inner driver handle this first to create the netvsc channel
760          * NOTE! Once the channel is created, we may get a receive callback
761          * (RndisFilterOnReceive()) before this call is completed
762          */
763         ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
764         if (ret != 0) {
765                 kfree(rndisDevice);
766                 return ret;
767         }
768
769
770         /* Initialize the rndis device */
771         netDevice = Device->Extension;
772         /* ASSERT(netDevice); */
773         /* ASSERT(netDevice->Device); */
774
775         netDevice->Extension = rndisDevice;
776         rndisDevice->NetDevice = netDevice;
777
778         /* Send the rndis initialization message */
779         ret = RndisFilterInitDevice(rndisDevice);
780         if (ret != 0) {
781                 /*
782                  * TODO: If rndis init failed, we will need to shut down the
783                  * channel
784                  */
785         }
786
787         /* Get the mac address */
788         ret = RndisFilterQueryDeviceMac(rndisDevice);
789         if (ret != 0) {
790                 /*
791                  * TODO: shutdown rndis device and the channel
792                  */
793         }
794
795         DPRINT_INFO(NETVSC, "Device 0x%p mac addr %pM",
796                     rndisDevice, rndisDevice->HwMacAddr);
797
798         memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, ETH_ALEN);
799
800         RndisFilterQueryDeviceLinkStatus(rndisDevice);
801
802         deviceInfo->LinkState = rndisDevice->LinkStatus;
803         DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice,
804                     ((deviceInfo->LinkState) ? ("down") : ("up")));
805
806         return ret;
807 }
808
809 static int RndisFilterOnDeviceRemove(struct hv_device *Device)
810 {
811         struct netvsc_device *netDevice = Device->Extension;
812         struct rndis_device *rndisDevice = netDevice->Extension;
813
814         /* Halt and release the rndis device */
815         RndisFilterHaltDevice(rndisDevice);
816
817         kfree(rndisDevice);
818         netDevice->Extension = NULL;
819
820         /* Pass control to inner driver to remove the device */
821         gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
822
823         return 0;
824 }
825
826 static void RndisFilterOnCleanup(struct hv_driver *Driver)
827 {
828 }
829
830 int RndisFilterOnOpen(struct hv_device *Device)
831 {
832         struct netvsc_device *netDevice = Device->Extension;
833
834         if (!netDevice)
835                 return -EINVAL;
836
837         return RndisFilterOpenDevice(netDevice->Extension);
838 }
839
840 int RndisFilterOnClose(struct hv_device *Device)
841 {
842         struct netvsc_device *netDevice = Device->Extension;
843
844         if (!netDevice)
845                 return -EINVAL;
846
847         return RndisFilterCloseDevice(netDevice->Extension);
848 }
849
850 static int RndisFilterOnSend(struct hv_device *Device,
851                              struct hv_netvsc_packet *Packet)
852 {
853         int ret;
854         struct rndis_filter_packet *filterPacket;
855         struct rndis_message *rndisMessage;
856         struct rndis_packet *rndisPacket;
857         u32 rndisMessageSize;
858
859         /* Add the rndis header */
860         filterPacket = (struct rndis_filter_packet *)Packet->Extension;
861         /* ASSERT(filterPacket); */
862
863         memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
864
865         rndisMessage = &filterPacket->Message;
866         rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
867
868         rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
869         rndisMessage->MessageLength = Packet->TotalDataBufferLength +
870                                       rndisMessageSize;
871
872         rndisPacket = &rndisMessage->Message.Packet;
873         rndisPacket->DataOffset = sizeof(struct rndis_packet);
874         rndisPacket->DataLength = Packet->TotalDataBufferLength;
875
876         Packet->IsDataPacket = true;
877         Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
878         Packet->PageBuffers[0].Offset =
879                         (unsigned long)rndisMessage & (PAGE_SIZE-1);
880         Packet->PageBuffers[0].Length = rndisMessageSize;
881
882         /* Save the packet send completion and context */
883         filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
884         filterPacket->CompletionContext =
885                                 Packet->Completion.Send.SendCompletionContext;
886
887         /* Use ours */
888         Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
889         Packet->Completion.Send.SendCompletionContext = filterPacket;
890
891         ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
892         if (ret != 0) {
893                 /*
894                  * Reset the completion to originals to allow retries from
895                  * above
896                  */
897                 Packet->Completion.Send.OnSendCompletion =
898                                 filterPacket->OnCompletion;
899                 Packet->Completion.Send.SendCompletionContext =
900                                 filterPacket->CompletionContext;
901         }
902
903         return ret;
904 }
905
906 static void RndisFilterOnSendCompletion(void *Context)
907 {
908         struct rndis_filter_packet *filterPacket = Context;
909
910         /* Pass it back to the original handler */
911         filterPacket->OnCompletion(filterPacket->CompletionContext);
912 }
913
914
915 static void RndisFilterOnSendRequestCompletion(void *Context)
916 {
917         /* Noop */
918 }