2 * Copyright (c) 2009, Microsoft Corporation.
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.
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
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.
18 * Haiyang Zhang <haiyangz@microsoft.com>
19 * Hank Janssen <hjanssen@microsoft.com>
21 #include <linux/kernel.h>
22 #include <linux/highmem.h>
23 #include <linux/slab.h>
25 #include <linux/if_ether.h>
29 #include "NetVscApi.h"
30 #include "rndis_filter.h"
33 struct rndis_filter_driver_object
{
34 /* The original driver */
35 struct netvsc_driver InnerDriver
;
38 enum rndis_device_state
{
39 RNDIS_DEV_UNINITIALIZED
= 0,
40 RNDIS_DEV_INITIALIZING
,
41 RNDIS_DEV_INITIALIZED
,
42 RNDIS_DEV_DATAINITIALIZED
,
46 struct netvsc_device
*NetDevice
;
48 enum rndis_device_state State
;
50 atomic_t NewRequestId
;
52 spinlock_t request_lock
;
53 struct list_head RequestList
;
55 unsigned char HwMacAddr
[ETH_ALEN
];
58 struct rndis_request
{
59 struct list_head ListEntry
;
60 struct osd_waitevent
*WaitEvent
;
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
67 struct rndis_message ResponseMessage
;
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
;
77 struct rndis_filter_packet
{
78 void *CompletionContext
;
79 void (*OnCompletion
)(void *context
);
80 struct rndis_message Message
;
84 static int RndisFilterOnDeviceAdd(struct hv_device
*Device
,
85 void *AdditionalInfo
);
87 static int RndisFilterOnDeviceRemove(struct hv_device
*Device
);
89 static void RndisFilterOnCleanup(struct hv_driver
*Driver
);
91 static int RndisFilterOnSend(struct hv_device
*Device
,
92 struct hv_netvsc_packet
*Packet
);
94 static void RndisFilterOnSendCompletion(void *Context
);
96 static void RndisFilterOnSendRequestCompletion(void *Context
);
99 /* The one and only */
100 static struct rndis_filter_driver_object gRndisFilter
;
102 static struct rndis_device
*GetRndisDevice(void)
104 struct rndis_device
*device
;
106 device
= kzalloc(sizeof(struct rndis_device
), GFP_KERNEL
);
110 spin_lock_init(&device
->request_lock
);
112 INIT_LIST_HEAD(&device
->RequestList
);
114 device
->State
= RNDIS_DEV_UNINITIALIZED
;
119 static struct rndis_request
*GetRndisRequest(struct rndis_device
*Device
,
123 struct rndis_request
*request
;
124 struct rndis_message
*rndisMessage
;
125 struct rndis_set_request
*set
;
128 request
= kzalloc(sizeof(struct rndis_request
), GFP_KERNEL
);
132 request
->WaitEvent
= osd_WaitEventCreate();
133 if (!request
->WaitEvent
) {
138 rndisMessage
= &request
->RequestMessage
;
139 rndisMessage
->NdisMessageType
= MessageType
;
140 rndisMessage
->MessageLength
= MessageLength
;
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
147 set
= &rndisMessage
->Message
.SetRequest
;
148 set
->RequestId
= atomic_inc_return(&Device
->NewRequestId
);
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
);
158 static void PutRndisRequest(struct rndis_device
*Device
,
159 struct rndis_request
*Request
)
163 spin_lock_irqsave(&Device
->request_lock
, flags
);
164 list_del(&Request
->ListEntry
);
165 spin_unlock_irqrestore(&Device
->request_lock
, flags
);
167 kfree(Request
->WaitEvent
);
171 static void DumpRndisMessage(struct rndis_message
*RndisMessage
)
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, "
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
);
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, "
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
);
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, "
209 RndisMessage
->MessageLength
,
210 RndisMessage
->Message
.QueryComplete
.RequestId
,
211 RndisMessage
->Message
.QueryComplete
.Status
,
212 RndisMessage
->Message
.QueryComplete
.InformationBufferLength
,
213 RndisMessage
->Message
.QueryComplete
.InformationBufferOffset
);
216 case REMOTE_NDIS_SET_CMPLT
:
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
);
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
);
234 DPRINT_DBG(NETVSC
, "0x%x (len %u)",
235 RndisMessage
->NdisMessageType
,
236 RndisMessage
->MessageLength
);
241 static int RndisFilterSendRequest(struct rndis_device
*Device
,
242 struct rndis_request
*Request
)
245 struct hv_netvsc_packet
*packet
;
247 DPRINT_ENTER(NETVSC
);
249 /* Setup the packet to send it */
250 packet
= &Request
->Packet
;
252 packet
->IsDataPacket
= false;
253 packet
->TotalDataBufferLength
= Request
->RequestMessage
.MessageLength
;
254 packet
->PageBufferCount
= 1;
256 packet
->PageBuffers
[0].Pfn
= virt_to_phys(&Request
->RequestMessage
) >>
258 packet
->PageBuffers
[0].Length
= Request
->RequestMessage
.MessageLength
;
259 packet
->PageBuffers
[0].Offset
=
260 (unsigned long)&Request
->RequestMessage
& (PAGE_SIZE
- 1);
262 packet
->Completion
.Send
.SendCompletionContext
= Request
;/* packet; */
263 packet
->Completion
.Send
.OnSendCompletion
=
264 RndisFilterOnSendRequestCompletion
;
265 packet
->Completion
.Send
.SendCompletionTid
= (unsigned long)Device
;
267 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
->NetDevice
->Device
, packet
);
272 static void RndisFilterReceiveResponse(struct rndis_device
*Device
,
273 struct rndis_message
*Response
)
275 struct rndis_request
*request
= NULL
;
279 DPRINT_ENTER(NETVSC
);
281 spin_lock_irqsave(&Device
->request_lock
, flags
);
282 list_for_each_entry(request
, &Device
->RequestList
, ListEntry
) {
284 * All request/response message contains RequestId as the 1st
287 if (request
->RequestMessage
.Message
.InitializeRequest
.RequestId
288 == Response
->Message
.InitializeComplete
.RequestId
) {
289 DPRINT_DBG(NETVSC
, "found rndis request for "
290 "this response (id 0x%x req type 0x%x res "
292 request
->RequestMessage
.Message
.InitializeRequest
.RequestId
,
293 request
->RequestMessage
.NdisMessageType
,
294 Response
->NdisMessageType
);
300 spin_unlock_irqrestore(&Device
->request_lock
, flags
);
303 if (Response
->MessageLength
<= sizeof(struct rndis_message
)) {
304 memcpy(&request
->ResponseMessage
, Response
,
305 Response
->MessageLength
);
307 DPRINT_ERR(NETVSC
, "rndis response buffer overflow "
308 "detected (size %u max %zu)",
309 Response
->MessageLength
,
310 sizeof(struct rndis_filter_packet
));
312 if (Response
->NdisMessageType
==
313 REMOTE_NDIS_RESET_CMPLT
) {
314 /* does not have a request id field */
315 request
->ResponseMessage
.Message
.ResetComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
317 request
->ResponseMessage
.Message
.InitializeComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
321 osd_WaitEventSet(request
->WaitEvent
);
323 DPRINT_ERR(NETVSC
, "no rndis request found for this response "
324 "(id 0x%x res type 0x%x)",
325 Response
->Message
.InitializeComplete
.RequestId
,
326 Response
->NdisMessageType
);
332 static void RndisFilterReceiveIndicateStatus(struct rndis_device
*Device
,
333 struct rndis_message
*Response
)
335 struct rndis_indicate_status
*indicate
=
336 &Response
->Message
.IndicateStatus
;
338 if (indicate
->Status
== RNDIS_STATUS_MEDIA_CONNECT
) {
339 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 1);
340 } else if (indicate
->Status
== RNDIS_STATUS_MEDIA_DISCONNECT
) {
341 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 0);
349 static void RndisFilterReceiveData(struct rndis_device
*Device
,
350 struct rndis_message
*Message
,
351 struct hv_netvsc_packet
*Packet
)
353 struct rndis_packet
*rndisPacket
;
356 DPRINT_ENTER(NETVSC
);
358 /* empty ethernet frame ?? */
359 /* ASSERT(Packet->PageBuffers[0].Length > */
360 /* RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
362 rndisPacket
= &Message
->Message
.Packet
;
365 * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
366 * netvsc packet (ie TotalDataBufferLength != MessageLength)
369 /* Remove the rndis header and pass it back up the stack */
370 dataOffset
= RNDIS_HEADER_SIZE
+ rndisPacket
->DataOffset
;
372 Packet
->TotalDataBufferLength
-= dataOffset
;
373 Packet
->PageBuffers
[0].Offset
+= dataOffset
;
374 Packet
->PageBuffers
[0].Length
-= dataOffset
;
376 Packet
->IsDataPacket
= true;
378 gRndisFilter
.InnerDriver
.OnReceiveCallback(Device
->NetDevice
->Device
,
384 static int RndisFilterOnReceive(struct hv_device
*Device
,
385 struct hv_netvsc_packet
*Packet
)
387 struct netvsc_device
*netDevice
= Device
->Extension
;
388 struct rndis_device
*rndisDevice
;
389 struct rndis_message rndisMessage
;
390 struct rndis_message
*rndisHeader
;
392 DPRINT_ENTER(NETVSC
);
397 /* Make sure the rndis device state is initialized */
398 if (!netDevice
->Extension
) {
399 DPRINT_ERR(NETVSC
, "got rndis message but no rndis device..."
400 "dropping this message!");
405 rndisDevice
= (struct rndis_device
*)netDevice
->Extension
;
406 if (rndisDevice
->State
== RNDIS_DEV_UNINITIALIZED
) {
407 DPRINT_ERR(NETVSC
, "got rndis message but rndis device "
408 "uninitialized...dropping this message!");
413 rndisHeader
= (struct rndis_message
*)kmap_atomic(
414 pfn_to_page(Packet
->PageBuffers
[0].Pfn
), KM_IRQ0
);
416 rndisHeader
= (void *)((unsigned long)rndisHeader
+
417 Packet
->PageBuffers
[0].Offset
);
419 /* Make sure we got a valid rndis message */
421 * FIXME: There seems to be a bug in set completion msg where its
422 * MessageLength is 16 bytes but the ByteCount field in the xfer page
423 * range shows 52 bytes
426 if (Packet
->TotalDataBufferLength
!= rndisHeader
->MessageLength
) {
427 kunmap_atomic(rndisHeader
- Packet
->PageBuffers
[0].Offset
,
430 DPRINT_ERR(NETVSC
, "invalid rndis message? (expected %u "
431 "bytes got %u)...dropping this message!",
432 rndisHeader
->MessageLength
,
433 Packet
->TotalDataBufferLength
);
439 if ((rndisHeader
->NdisMessageType
!= REMOTE_NDIS_PACKET_MSG
) &&
440 (rndisHeader
->MessageLength
> sizeof(struct rndis_message
))) {
441 DPRINT_ERR(NETVSC
, "incoming rndis message buffer overflow "
442 "detected (got %u, max %zu)...marking it an error!",
443 rndisHeader
->MessageLength
,
444 sizeof(struct rndis_message
));
447 memcpy(&rndisMessage
, rndisHeader
,
448 (rndisHeader
->MessageLength
> sizeof(struct rndis_message
)) ?
449 sizeof(struct rndis_message
) :
450 rndisHeader
->MessageLength
);
452 kunmap_atomic(rndisHeader
- Packet
->PageBuffers
[0].Offset
, KM_IRQ0
);
454 DumpRndisMessage(&rndisMessage
);
456 switch (rndisMessage
.NdisMessageType
) {
457 case REMOTE_NDIS_PACKET_MSG
:
459 RndisFilterReceiveData(rndisDevice
, &rndisMessage
, Packet
);
462 case REMOTE_NDIS_INITIALIZE_CMPLT
:
463 case REMOTE_NDIS_QUERY_CMPLT
:
464 case REMOTE_NDIS_SET_CMPLT
:
465 /* case REMOTE_NDIS_RESET_CMPLT: */
466 /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
467 /* completion msgs */
468 RndisFilterReceiveResponse(rndisDevice
, &rndisMessage
);
471 case REMOTE_NDIS_INDICATE_STATUS_MSG
:
472 /* notification msgs */
473 RndisFilterReceiveIndicateStatus(rndisDevice
, &rndisMessage
);
476 DPRINT_ERR(NETVSC
, "unhandled rndis message (type %u len %u)",
477 rndisMessage
.NdisMessageType
,
478 rndisMessage
.MessageLength
);
486 static int RndisFilterQueryDevice(struct rndis_device
*Device
, u32 Oid
,
487 void *Result
, u32
*ResultSize
)
489 struct rndis_request
*request
;
490 u32 inresultSize
= *ResultSize
;
491 struct rndis_query_request
*query
;
492 struct rndis_query_complete
*queryComplete
;
495 DPRINT_ENTER(NETVSC
);
501 request
= GetRndisRequest(Device
, REMOTE_NDIS_QUERY_MSG
,
502 RNDIS_MESSAGE_SIZE(struct rndis_query_request
));
508 /* Setup the rndis query */
509 query
= &request
->RequestMessage
.Message
.QueryRequest
;
511 query
->InformationBufferOffset
= sizeof(struct rndis_query_request
);
512 query
->InformationBufferLength
= 0;
513 query
->DeviceVcHandle
= 0;
515 ret
= RndisFilterSendRequest(Device
, request
);
519 osd_WaitEventWait(request
->WaitEvent
);
521 /* Copy the response back */
522 queryComplete
= &request
->ResponseMessage
.Message
.QueryComplete
;
524 if (queryComplete
->InformationBufferLength
> inresultSize
) {
530 (void *)((unsigned long)queryComplete
+
531 queryComplete
->InformationBufferOffset
),
532 queryComplete
->InformationBufferLength
);
534 *ResultSize
= queryComplete
->InformationBufferLength
;
538 PutRndisRequest(Device
, request
);
544 static int RndisFilterQueryDeviceMac(struct rndis_device
*Device
)
548 return RndisFilterQueryDevice(Device
,
549 RNDIS_OID_802_3_PERMANENT_ADDRESS
,
550 Device
->HwMacAddr
, &size
);
553 static int RndisFilterQueryDeviceLinkStatus(struct rndis_device
*Device
)
555 u32 size
= sizeof(u32
);
557 return RndisFilterQueryDevice(Device
,
558 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS
,
559 &Device
->LinkStatus
, &size
);
562 static int RndisFilterSetPacketFilter(struct rndis_device
*Device
,
565 struct rndis_request
*request
;
566 struct rndis_set_request
*set
;
567 struct rndis_set_complete
*setComplete
;
571 DPRINT_ENTER(NETVSC
);
573 /* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
574 /* sizeof(struct rndis_message)); */
576 request
= GetRndisRequest(Device
, REMOTE_NDIS_SET_MSG
,
577 RNDIS_MESSAGE_SIZE(struct rndis_set_request
) +
584 /* Setup the rndis set */
585 set
= &request
->RequestMessage
.Message
.SetRequest
;
586 set
->Oid
= RNDIS_OID_GEN_CURRENT_PACKET_FILTER
;
587 set
->InformationBufferLength
= sizeof(u32
);
588 set
->InformationBufferOffset
= sizeof(struct rndis_set_request
);
590 memcpy((void *)(unsigned long)set
+ sizeof(struct rndis_set_request
),
591 &NewFilter
, sizeof(u32
));
593 ret
= RndisFilterSendRequest(Device
, request
);
597 ret
= osd_WaitEventWaitEx(request
->WaitEvent
, 2000/*2sec*/);
600 DPRINT_ERR(NETVSC
, "timeout before we got a set response...");
602 * We cant deallocate the request since we may still receive a
603 * send completion for it.
609 setComplete
= &request
->ResponseMessage
.Message
.SetComplete
;
610 status
= setComplete
->Status
;
615 PutRndisRequest(Device
, request
);
622 int RndisFilterInit(struct netvsc_driver
*Driver
)
624 DPRINT_ENTER(NETVSC
);
626 DPRINT_DBG(NETVSC
, "sizeof(struct rndis_filter_packet) == %zd",
627 sizeof(struct rndis_filter_packet
));
629 Driver
->RequestExtSize
= sizeof(struct rndis_filter_packet
);
631 /* Driver->Context = rndisDriver; */
633 memset(&gRndisFilter
, 0, sizeof(struct rndis_filter_driver_object
));
635 /*rndisDriver->Driver = Driver;
637 ASSERT(Driver->OnLinkStatusChanged);
638 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
640 /* Save the original dispatch handlers before we override it */
641 gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd
= Driver
->Base
.OnDeviceAdd
;
642 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove
=
643 Driver
->Base
.OnDeviceRemove
;
644 gRndisFilter
.InnerDriver
.Base
.OnCleanup
= Driver
->Base
.OnCleanup
;
646 /* ASSERT(Driver->OnSend); */
647 /* ASSERT(Driver->OnReceiveCallback); */
648 gRndisFilter
.InnerDriver
.OnSend
= Driver
->OnSend
;
649 gRndisFilter
.InnerDriver
.OnReceiveCallback
= Driver
->OnReceiveCallback
;
650 gRndisFilter
.InnerDriver
.OnLinkStatusChanged
=
651 Driver
->OnLinkStatusChanged
;
654 Driver
->Base
.OnDeviceAdd
= RndisFilterOnDeviceAdd
;
655 Driver
->Base
.OnDeviceRemove
= RndisFilterOnDeviceRemove
;
656 Driver
->Base
.OnCleanup
= RndisFilterOnCleanup
;
657 Driver
->OnSend
= RndisFilterOnSend
;
658 /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
659 Driver
->OnReceiveCallback
= RndisFilterOnReceive
;
666 static int RndisFilterInitDevice(struct rndis_device
*Device
)
668 struct rndis_request
*request
;
669 struct rndis_initialize_request
*init
;
670 struct rndis_initialize_complete
*initComplete
;
674 DPRINT_ENTER(NETVSC
);
676 request
= GetRndisRequest(Device
, REMOTE_NDIS_INITIALIZE_MSG
,
677 RNDIS_MESSAGE_SIZE(struct rndis_initialize_request
));
683 /* Setup the rndis set */
684 init
= &request
->RequestMessage
.Message
.InitializeRequest
;
685 init
->MajorVersion
= RNDIS_MAJOR_VERSION
;
686 init
->MinorVersion
= RNDIS_MINOR_VERSION
;
687 /* FIXME: Use 1536 - rounded ethernet frame size */
688 init
->MaxTransferSize
= 2048;
690 Device
->State
= RNDIS_DEV_INITIALIZING
;
692 ret
= RndisFilterSendRequest(Device
, request
);
694 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
698 osd_WaitEventWait(request
->WaitEvent
);
700 initComplete
= &request
->ResponseMessage
.Message
.InitializeComplete
;
701 status
= initComplete
->Status
;
702 if (status
== RNDIS_STATUS_SUCCESS
) {
703 Device
->State
= RNDIS_DEV_INITIALIZED
;
706 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
712 PutRndisRequest(Device
, request
);
718 static void RndisFilterHaltDevice(struct rndis_device
*Device
)
720 struct rndis_request
*request
;
721 struct rndis_halt_request
*halt
;
723 DPRINT_ENTER(NETVSC
);
725 /* Attempt to do a rndis device halt */
726 request
= GetRndisRequest(Device
, REMOTE_NDIS_HALT_MSG
,
727 RNDIS_MESSAGE_SIZE(struct rndis_halt_request
));
731 /* Setup the rndis set */
732 halt
= &request
->RequestMessage
.Message
.HaltRequest
;
733 halt
->RequestId
= atomic_inc_return(&Device
->NewRequestId
);
735 /* Ignore return since this msg is optional. */
736 RndisFilterSendRequest(Device
, request
);
738 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
742 PutRndisRequest(Device
, request
);
747 static int RndisFilterOpenDevice(struct rndis_device
*Device
)
751 DPRINT_ENTER(NETVSC
);
753 if (Device
->State
!= RNDIS_DEV_INITIALIZED
)
756 ret
= RndisFilterSetPacketFilter(Device
,
757 NDIS_PACKET_TYPE_BROADCAST
|
758 NDIS_PACKET_TYPE_DIRECTED
);
760 Device
->State
= RNDIS_DEV_DATAINITIALIZED
;
766 static int RndisFilterCloseDevice(struct rndis_device
*Device
)
770 DPRINT_ENTER(NETVSC
);
772 if (Device
->State
!= RNDIS_DEV_DATAINITIALIZED
)
775 ret
= RndisFilterSetPacketFilter(Device
, 0);
777 Device
->State
= RNDIS_DEV_INITIALIZED
;
784 static int RndisFilterOnDeviceAdd(struct hv_device
*Device
,
785 void *AdditionalInfo
)
788 struct netvsc_device
*netDevice
;
789 struct rndis_device
*rndisDevice
;
790 struct netvsc_device_info
*deviceInfo
= AdditionalInfo
;
792 DPRINT_ENTER(NETVSC
);
794 rndisDevice
= GetRndisDevice();
800 DPRINT_DBG(NETVSC
, "rndis device object allocated - %p", rndisDevice
);
803 * Let the inner driver handle this first to create the netvsc channel
804 * NOTE! Once the channel is created, we may get a receive callback
805 * (RndisFilterOnReceive()) before this call is completed
807 ret
= gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd(Device
, AdditionalInfo
);
815 /* Initialize the rndis device */
816 netDevice
= Device
->Extension
;
817 /* ASSERT(netDevice); */
818 /* ASSERT(netDevice->Device); */
820 netDevice
->Extension
= rndisDevice
;
821 rndisDevice
->NetDevice
= netDevice
;
823 /* Send the rndis initialization message */
824 ret
= RndisFilterInitDevice(rndisDevice
);
827 * TODO: If rndis init failed, we will need to shut down the
832 /* Get the mac address */
833 ret
= RndisFilterQueryDeviceMac(rndisDevice
);
836 * TODO: shutdown rndis device and the channel
840 DPRINT_INFO(NETVSC
, "Device 0x%p mac addr %pM",
841 rndisDevice
, rndisDevice
->HwMacAddr
);
843 memcpy(deviceInfo
->MacAddr
, rndisDevice
->HwMacAddr
, ETH_ALEN
);
845 RndisFilterQueryDeviceLinkStatus(rndisDevice
);
847 deviceInfo
->LinkState
= rndisDevice
->LinkStatus
;
848 DPRINT_INFO(NETVSC
, "Device 0x%p link state %s", rndisDevice
,
849 ((deviceInfo
->LinkState
) ? ("down") : ("up")));
856 static int RndisFilterOnDeviceRemove(struct hv_device
*Device
)
858 struct netvsc_device
*netDevice
= Device
->Extension
;
859 struct rndis_device
*rndisDevice
= netDevice
->Extension
;
861 DPRINT_ENTER(NETVSC
);
863 /* Halt and release the rndis device */
864 RndisFilterHaltDevice(rndisDevice
);
867 netDevice
->Extension
= NULL
;
869 /* Pass control to inner driver to remove the device */
870 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove(Device
);
877 static void RndisFilterOnCleanup(struct hv_driver
*Driver
)
879 DPRINT_ENTER(NETVSC
);
884 int RndisFilterOnOpen(struct hv_device
*Device
)
887 struct netvsc_device
*netDevice
= Device
->Extension
;
889 DPRINT_ENTER(NETVSC
);
894 ret
= RndisFilterOpenDevice(netDevice
->Extension
);
901 int RndisFilterOnClose(struct hv_device
*Device
)
904 struct netvsc_device
*netDevice
= Device
->Extension
;
906 DPRINT_ENTER(NETVSC
);
911 ret
= RndisFilterCloseDevice(netDevice
->Extension
);
918 static int RndisFilterOnSend(struct hv_device
*Device
,
919 struct hv_netvsc_packet
*Packet
)
922 struct rndis_filter_packet
*filterPacket
;
923 struct rndis_message
*rndisMessage
;
924 struct rndis_packet
*rndisPacket
;
925 u32 rndisMessageSize
;
927 DPRINT_ENTER(NETVSC
);
929 /* Add the rndis header */
930 filterPacket
= (struct rndis_filter_packet
*)Packet
->Extension
;
931 /* ASSERT(filterPacket); */
933 memset(filterPacket
, 0, sizeof(struct rndis_filter_packet
));
935 rndisMessage
= &filterPacket
->Message
;
936 rndisMessageSize
= RNDIS_MESSAGE_SIZE(struct rndis_packet
);
938 rndisMessage
->NdisMessageType
= REMOTE_NDIS_PACKET_MSG
;
939 rndisMessage
->MessageLength
= Packet
->TotalDataBufferLength
+
942 rndisPacket
= &rndisMessage
->Message
.Packet
;
943 rndisPacket
->DataOffset
= sizeof(struct rndis_packet
);
944 rndisPacket
->DataLength
= Packet
->TotalDataBufferLength
;
946 Packet
->IsDataPacket
= true;
947 Packet
->PageBuffers
[0].Pfn
= virt_to_phys(rndisMessage
) >> PAGE_SHIFT
;
948 Packet
->PageBuffers
[0].Offset
=
949 (unsigned long)rndisMessage
& (PAGE_SIZE
-1);
950 Packet
->PageBuffers
[0].Length
= rndisMessageSize
;
952 /* Save the packet send completion and context */
953 filterPacket
->OnCompletion
= Packet
->Completion
.Send
.OnSendCompletion
;
954 filterPacket
->CompletionContext
=
955 Packet
->Completion
.Send
.SendCompletionContext
;
958 Packet
->Completion
.Send
.OnSendCompletion
= RndisFilterOnSendCompletion
;
959 Packet
->Completion
.Send
.SendCompletionContext
= filterPacket
;
961 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
, Packet
);
964 * Reset the completion to originals to allow retries from
967 Packet
->Completion
.Send
.OnSendCompletion
=
968 filterPacket
->OnCompletion
;
969 Packet
->Completion
.Send
.SendCompletionContext
=
970 filterPacket
->CompletionContext
;
978 static void RndisFilterOnSendCompletion(void *Context
)
980 struct rndis_filter_packet
*filterPacket
= Context
;
982 DPRINT_ENTER(NETVSC
);
984 /* Pass it back to the original handler */
985 filterPacket
->OnCompletion(filterPacket
->CompletionContext
);
991 static void RndisFilterOnSendRequestCompletion(void *Context
)
993 DPRINT_ENTER(NETVSC
);