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