3 * Copyright (c) 2009, Microsoft Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
24 #include <linux/kernel.h>
25 #include <linux/highmem.h>
26 #include <asm/kmap_types.h>
29 #include "include/logging.h"
31 #include "include/NetVscApi.h"
32 #include "RndisFilter.h"
38 typedef struct _RNDIS_FILTER_DRIVER_OBJECT
{
39 /* The original driver */
40 NETVSC_DRIVER_OBJECT InnerDriver
;
42 } RNDIS_FILTER_DRIVER_OBJECT
;
45 RNDIS_DEV_UNINITIALIZED
= 0,
46 RNDIS_DEV_INITIALIZING
,
47 RNDIS_DEV_INITIALIZED
,
48 RNDIS_DEV_DATAINITIALIZED
,
51 typedef struct _RNDIS_DEVICE
{
52 struct NETVSC_DEVICE
*NetDevice
;
54 RNDIS_DEVICE_STATE State
;
56 atomic_t NewRequestId
;
58 spinlock_t request_lock
;
59 LIST_ENTRY RequestList
;
61 unsigned char HwMacAddr
[HW_MACADDR_LEN
];
65 typedef struct _RNDIS_REQUEST
{
67 struct osd_waitevent
*WaitEvent
;
69 /* FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response, */
70 /* we can either define a max response message or add a response buffer variable above this field */
71 RNDIS_MESSAGE ResponseMessage
;
73 /* Simplify allocation by having a netvsc packet inline */
74 struct hv_netvsc_packet Packet
;
76 /* FIXME: We assumed a fixed size request here. */
77 RNDIS_MESSAGE RequestMessage
;
81 typedef struct _RNDIS_FILTER_PACKET
{
82 void *CompletionContext
;
83 PFN_ON_SENDRECVCOMPLETION OnCompletion
;
85 RNDIS_MESSAGE Message
;
86 } RNDIS_FILTER_PACKET
;
89 /* Internal routines */
92 RndisFilterSendRequest(
94 RNDIS_REQUEST
*Request
98 RndisFilterReceiveResponse(
100 RNDIS_MESSAGE
*Response
104 RndisFilterReceiveIndicateStatus(
105 RNDIS_DEVICE
*Device
,
106 RNDIS_MESSAGE
*Response
110 RndisFilterReceiveData(
111 RNDIS_DEVICE
*Device
,
112 RNDIS_MESSAGE
*Message
,
113 struct hv_netvsc_packet
*Packet
117 RndisFilterOnReceive(
118 struct hv_device
*Device
,
119 struct hv_netvsc_packet
*Packet
123 RndisFilterQueryDevice(
124 RNDIS_DEVICE
*Device
,
131 RndisFilterQueryDeviceMac(
136 RndisFilterQueryDeviceLinkStatus(
141 RndisFilterSetPacketFilter(
142 RNDIS_DEVICE
*Device
,
147 RndisFilterInitDevice(
152 RndisFilterOpenDevice(
157 RndisFilterCloseDevice(
162 RndisFilterOnDeviceAdd(
163 struct hv_device
*Device
,
168 RndisFilterOnDeviceRemove(
169 struct hv_device
*Device
173 RndisFilterOnCleanup(
174 struct hv_driver
*Driver
179 struct hv_device
*Device
184 struct hv_device
*Device
189 struct hv_device
*Device
,
190 struct hv_netvsc_packet
*Packet
194 RndisFilterOnSendCompletion(
199 RndisFilterOnSendRequestCompletion(
207 /* The one and only */
208 static RNDIS_FILTER_DRIVER_OBJECT gRndisFilter
;
210 static inline RNDIS_DEVICE
* GetRndisDevice(void)
212 RNDIS_DEVICE
*device
;
214 device
= kzalloc(sizeof(RNDIS_DEVICE
), GFP_KERNEL
);
220 spin_lock_init(&device
->request_lock
);
222 INITIALIZE_LIST_HEAD(&device
->RequestList
);
224 device
->State
= RNDIS_DEV_UNINITIALIZED
;
229 static inline void PutRndisDevice(RNDIS_DEVICE
*Device
)
234 static inline RNDIS_REQUEST
* GetRndisRequest(RNDIS_DEVICE
*Device
, u32 MessageType
, u32 MessageLength
)
236 RNDIS_REQUEST
*request
;
237 RNDIS_MESSAGE
*rndisMessage
;
238 RNDIS_SET_REQUEST
*set
;
241 request
= kzalloc(sizeof(RNDIS_REQUEST
), GFP_KERNEL
);
247 request
->WaitEvent
= WaitEventCreate();
248 if (!request
->WaitEvent
)
254 rndisMessage
= &request
->RequestMessage
;
255 rndisMessage
->NdisMessageType
= MessageType
;
256 rndisMessage
->MessageLength
= MessageLength
;
258 /* Set the request id. This field is always after the rndis header for request/response packet types so */
259 /* we just used the SetRequest as a template */
260 set
= &rndisMessage
->Message
.SetRequest
;
261 set
->RequestId
= atomic_inc_return(&Device
->NewRequestId
);
263 /* Add to the request list */
264 spin_lock_irqsave(&Device
->request_lock
, flags
);
265 INSERT_TAIL_LIST(&Device
->RequestList
, &request
->ListEntry
);
266 spin_unlock_irqrestore(&Device
->request_lock
, flags
);
271 static inline void PutRndisRequest(RNDIS_DEVICE
*Device
, RNDIS_REQUEST
*Request
)
275 spin_lock_irqsave(&Device
->request_lock
, flags
);
276 REMOVE_ENTRY_LIST(&Request
->ListEntry
);
277 spin_unlock_irqrestore(&Device
->request_lock
, flags
);
279 kfree(Request
->WaitEvent
);
283 static inline void DumpRndisMessage(RNDIS_MESSAGE
*RndisMessage
)
285 switch (RndisMessage
->NdisMessageType
)
287 case REMOTE_NDIS_PACKET_MSG
:
288 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_PACKET_MSG (len %u, data offset %u data len %u, # oob %u, oob offset %u, oob len %u, pkt offset %u, pkt len %u",
289 RndisMessage
->MessageLength
,
290 RndisMessage
->Message
.Packet
.DataOffset
,
291 RndisMessage
->Message
.Packet
.DataLength
,
292 RndisMessage
->Message
.Packet
.NumOOBDataElements
,
293 RndisMessage
->Message
.Packet
.OOBDataOffset
,
294 RndisMessage
->Message
.Packet
.OOBDataLength
,
295 RndisMessage
->Message
.Packet
.PerPacketInfoOffset
,
296 RndisMessage
->Message
.Packet
.PerPacketInfoLength
);
299 case REMOTE_NDIS_INITIALIZE_CMPLT
:
300 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_INITIALIZE_CMPLT (len %u, id 0x%x, status 0x%x, major %d, minor %d, device flags %d, max xfer size 0x%x, max pkts %u, pkt aligned %u)",
301 RndisMessage
->MessageLength
,
302 RndisMessage
->Message
.InitializeComplete
.RequestId
,
303 RndisMessage
->Message
.InitializeComplete
.Status
,
304 RndisMessage
->Message
.InitializeComplete
.MajorVersion
,
305 RndisMessage
->Message
.InitializeComplete
.MinorVersion
,
306 RndisMessage
->Message
.InitializeComplete
.DeviceFlags
,
307 RndisMessage
->Message
.InitializeComplete
.MaxTransferSize
,
308 RndisMessage
->Message
.InitializeComplete
.MaxPacketsPerMessage
,
309 RndisMessage
->Message
.InitializeComplete
.PacketAlignmentFactor
);
312 case REMOTE_NDIS_QUERY_CMPLT
:
313 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_QUERY_CMPLT (len %u, id 0x%x, status 0x%x, buf len %u, buf offset %u)",
314 RndisMessage
->MessageLength
,
315 RndisMessage
->Message
.QueryComplete
.RequestId
,
316 RndisMessage
->Message
.QueryComplete
.Status
,
317 RndisMessage
->Message
.QueryComplete
.InformationBufferLength
,
318 RndisMessage
->Message
.QueryComplete
.InformationBufferOffset
);
321 case REMOTE_NDIS_SET_CMPLT
:
322 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
323 RndisMessage
->MessageLength
,
324 RndisMessage
->Message
.SetComplete
.RequestId
,
325 RndisMessage
->Message
.SetComplete
.Status
);
328 case REMOTE_NDIS_INDICATE_STATUS_MSG
:
329 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_INDICATE_STATUS_MSG (len %u, status 0x%x, buf len %u, buf offset %u)",
330 RndisMessage
->MessageLength
,
331 RndisMessage
->Message
.IndicateStatus
.Status
,
332 RndisMessage
->Message
.IndicateStatus
.StatusBufferLength
,
333 RndisMessage
->Message
.IndicateStatus
.StatusBufferOffset
);
337 DPRINT_DBG(NETVSC
, "0x%x (len %u)",
338 RndisMessage
->NdisMessageType
,
339 RndisMessage
->MessageLength
);
345 RndisFilterSendRequest(
346 RNDIS_DEVICE
*Device
,
347 RNDIS_REQUEST
*Request
351 struct hv_netvsc_packet
*packet
;
353 DPRINT_ENTER(NETVSC
);
355 /* Setup the packet to send it */
356 packet
= &Request
->Packet
;
358 packet
->IsDataPacket
= false;
359 packet
->TotalDataBufferLength
= Request
->RequestMessage
.MessageLength
;
360 packet
->PageBufferCount
= 1;
362 packet
->PageBuffers
[0].Pfn
= virt_to_phys(&Request
->RequestMessage
) >> PAGE_SHIFT
;
363 packet
->PageBuffers
[0].Length
= Request
->RequestMessage
.MessageLength
;
364 packet
->PageBuffers
[0].Offset
= (unsigned long)&Request
->RequestMessage
& (PAGE_SIZE
-1);
366 packet
->Completion
.Send
.SendCompletionContext
= Request
;/* packet; */
367 packet
->Completion
.Send
.OnSendCompletion
= RndisFilterOnSendRequestCompletion
;
368 packet
->Completion
.Send
.SendCompletionTid
= (unsigned long)Device
;
370 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
->NetDevice
->Device
, packet
);
377 RndisFilterReceiveResponse(
378 RNDIS_DEVICE
*Device
,
379 RNDIS_MESSAGE
*Response
384 RNDIS_REQUEST
*request
=NULL
;
388 DPRINT_ENTER(NETVSC
);
390 spin_lock_irqsave(&Device
->request_lock
, flags
);
391 ITERATE_LIST_ENTRIES(anchor
, curr
, &Device
->RequestList
)
393 request
= CONTAINING_RECORD(curr
, RNDIS_REQUEST
, ListEntry
);
395 /* All request/response message contains RequestId as the 1st field */
396 if (request
->RequestMessage
.Message
.InitializeRequest
.RequestId
== Response
->Message
.InitializeComplete
.RequestId
)
398 DPRINT_DBG(NETVSC
, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
399 request
->RequestMessage
.Message
.InitializeRequest
.RequestId
, request
->RequestMessage
.NdisMessageType
, Response
->NdisMessageType
);
405 spin_unlock_irqrestore(&Device
->request_lock
, flags
);
409 if (Response
->MessageLength
<= sizeof(RNDIS_MESSAGE
))
411 memcpy(&request
->ResponseMessage
, Response
, Response
->MessageLength
);
415 DPRINT_ERR(NETVSC
, "rndis response buffer overflow detected (size %u max %zu)", Response
->MessageLength
, sizeof(RNDIS_FILTER_PACKET
));
417 if (Response
->NdisMessageType
== REMOTE_NDIS_RESET_CMPLT
) /* does not have a request id field */
419 request
->ResponseMessage
.Message
.ResetComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
423 request
->ResponseMessage
.Message
.InitializeComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
427 WaitEventSet(request
->WaitEvent
);
431 DPRINT_ERR(NETVSC
, "no rndis request found for this response (id 0x%x res type 0x%x)",
432 Response
->Message
.InitializeComplete
.RequestId
, Response
->NdisMessageType
);
439 RndisFilterReceiveIndicateStatus(
440 RNDIS_DEVICE
*Device
,
441 RNDIS_MESSAGE
*Response
444 RNDIS_INDICATE_STATUS
*indicate
= &Response
->Message
.IndicateStatus
;
446 if (indicate
->Status
== RNDIS_STATUS_MEDIA_CONNECT
)
448 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 1);
450 else if (indicate
->Status
== RNDIS_STATUS_MEDIA_DISCONNECT
)
452 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 0);
461 RndisFilterReceiveData(
462 RNDIS_DEVICE
*Device
,
463 RNDIS_MESSAGE
*Message
,
464 struct hv_netvsc_packet
*Packet
467 RNDIS_PACKET
*rndisPacket
;
470 DPRINT_ENTER(NETVSC
);
472 /* empty ethernet frame ?? */
473 ASSERT(Packet
->PageBuffers
[0].Length
> RNDIS_MESSAGE_SIZE(RNDIS_PACKET
));
475 rndisPacket
= &Message
->Message
.Packet
;
477 /* FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this */
478 /* netvsc packet (ie TotalDataBufferLength != MessageLength) */
480 /* Remove the rndis header and pass it back up the stack */
481 dataOffset
= RNDIS_HEADER_SIZE
+ rndisPacket
->DataOffset
;
483 Packet
->TotalDataBufferLength
-= dataOffset
;
484 Packet
->PageBuffers
[0].Offset
+= dataOffset
;
485 Packet
->PageBuffers
[0].Length
-= dataOffset
;
487 Packet
->IsDataPacket
= true;
489 gRndisFilter
.InnerDriver
.OnReceiveCallback(Device
->NetDevice
->Device
, Packet
);
495 RndisFilterOnReceive(
496 struct hv_device
*Device
,
497 struct hv_netvsc_packet
*Packet
500 struct NETVSC_DEVICE
*netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
501 RNDIS_DEVICE
*rndisDevice
;
502 RNDIS_MESSAGE rndisMessage
;
503 RNDIS_MESSAGE
*rndisHeader
;
505 DPRINT_ENTER(NETVSC
);
508 /* Make sure the rndis device state is initialized */
509 if (!netDevice
->Extension
)
511 DPRINT_ERR(NETVSC
, "got rndis message but no rndis device...dropping this message!");
516 rndisDevice
= (RNDIS_DEVICE
*)netDevice
->Extension
;
517 if (rndisDevice
->State
== RNDIS_DEV_UNINITIALIZED
)
519 DPRINT_ERR(NETVSC
, "got rndis message but rndis device uninitialized...dropping this message!");
524 rndisHeader
= (RNDIS_MESSAGE
*)kmap_atomic(pfn_to_page(Packet
->PageBuffers
[0].Pfn
), KM_IRQ0
);
526 rndisHeader
= (void*)((unsigned long)rndisHeader
+ Packet
->PageBuffers
[0].Offset
);
528 /* Make sure we got a valid rndis message */
529 /* FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but */
530 /* the ByteCount field in the xfer page range shows 52 bytes */
532 if ( Packet
->TotalDataBufferLength
!= rndisHeader
->MessageLength
)
534 kunmap_atomic(rndisHeader
- Packet
->PageBuffers
[0].Offset
, KM_IRQ0
);
536 DPRINT_ERR(NETVSC
, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
537 rndisHeader
->MessageLength
, Packet
->TotalDataBufferLength
);
543 if ((rndisHeader
->NdisMessageType
!= REMOTE_NDIS_PACKET_MSG
) && (rndisHeader
->MessageLength
> sizeof(RNDIS_MESSAGE
)))
545 DPRINT_ERR(NETVSC
, "incoming rndis message buffer overflow detected (got %u, max %zu)...marking it an error!",
546 rndisHeader
->MessageLength
, sizeof(RNDIS_MESSAGE
));
549 memcpy(&rndisMessage
, rndisHeader
, (rndisHeader
->MessageLength
> sizeof(RNDIS_MESSAGE
))?sizeof(RNDIS_MESSAGE
):rndisHeader
->MessageLength
);
551 kunmap_atomic(rndisHeader
- Packet
->PageBuffers
[0].Offset
, KM_IRQ0
);
553 DumpRndisMessage(&rndisMessage
);
555 switch (rndisMessage
.NdisMessageType
)
558 case REMOTE_NDIS_PACKET_MSG
:
559 RndisFilterReceiveData(rndisDevice
, &rndisMessage
, Packet
);
562 /* completion msgs */
563 case REMOTE_NDIS_INITIALIZE_CMPLT
:
564 case REMOTE_NDIS_QUERY_CMPLT
:
565 case REMOTE_NDIS_SET_CMPLT
:
566 /* case REMOTE_NDIS_RESET_CMPLT: */
567 /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
568 RndisFilterReceiveResponse(rndisDevice
, &rndisMessage
);
571 /* notification msgs */
572 case REMOTE_NDIS_INDICATE_STATUS_MSG
:
573 RndisFilterReceiveIndicateStatus(rndisDevice
, &rndisMessage
);
576 DPRINT_ERR(NETVSC
, "unhandled rndis message (type %u len %u)", rndisMessage
.NdisMessageType
, rndisMessage
.MessageLength
);
586 RndisFilterQueryDevice(
587 RNDIS_DEVICE
*Device
,
593 RNDIS_REQUEST
*request
;
594 u32 inresultSize
= *ResultSize
;
595 RNDIS_QUERY_REQUEST
*query
;
596 RNDIS_QUERY_COMPLETE
*queryComplete
;
599 DPRINT_ENTER(NETVSC
);
604 request
= GetRndisRequest(Device
, REMOTE_NDIS_QUERY_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST
));
611 /* Setup the rndis query */
612 query
= &request
->RequestMessage
.Message
.QueryRequest
;
614 query
->InformationBufferOffset
= sizeof(RNDIS_QUERY_REQUEST
);
615 query
->InformationBufferLength
= 0;
616 query
->DeviceVcHandle
= 0;
618 ret
= RndisFilterSendRequest(Device
, request
);
624 WaitEventWait(request
->WaitEvent
);
626 /* Copy the response back */
627 queryComplete
= &request
->ResponseMessage
.Message
.QueryComplete
;
629 if (queryComplete
->InformationBufferLength
> inresultSize
)
636 (void*)((unsigned long)queryComplete
+ queryComplete
->InformationBufferOffset
),
637 queryComplete
->InformationBufferLength
);
639 *ResultSize
= queryComplete
->InformationBufferLength
;
644 PutRndisRequest(Device
, request
);
652 RndisFilterQueryDeviceMac(
656 u32 size
=HW_MACADDR_LEN
;
658 return RndisFilterQueryDevice(Device
,
659 RNDIS_OID_802_3_PERMANENT_ADDRESS
,
665 RndisFilterQueryDeviceLinkStatus(
669 u32 size
=sizeof(u32
);
671 return RndisFilterQueryDevice(Device
,
672 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS
,
678 RndisFilterSetPacketFilter(
679 RNDIS_DEVICE
*Device
,
683 RNDIS_REQUEST
*request
;
684 RNDIS_SET_REQUEST
*set
;
685 RNDIS_SET_COMPLETE
*setComplete
;
689 DPRINT_ENTER(NETVSC
);
691 ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST
) + sizeof(u32
) <= sizeof(RNDIS_MESSAGE
));
693 request
= GetRndisRequest(Device
, REMOTE_NDIS_SET_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST
) + sizeof(u32
));
700 /* Setup the rndis set */
701 set
= &request
->RequestMessage
.Message
.SetRequest
;
702 set
->Oid
= RNDIS_OID_GEN_CURRENT_PACKET_FILTER
;
703 set
->InformationBufferLength
= sizeof(u32
);
704 set
->InformationBufferOffset
= sizeof(RNDIS_SET_REQUEST
);
706 memcpy((void*)(unsigned long)set
+ sizeof(RNDIS_SET_REQUEST
), &NewFilter
, sizeof(u32
));
708 ret
= RndisFilterSendRequest(Device
, request
);
714 ret
= WaitEventWaitEx(request
->WaitEvent
, 2000/*2sec*/);
718 DPRINT_ERR(NETVSC
, "timeout before we got a set response...");
719 /* We cant deallocate the request since we may still receive a send completion for it. */
728 setComplete
= &request
->ResponseMessage
.Message
.SetComplete
;
729 status
= setComplete
->Status
;
735 PutRndisRequest(Device
, request
);
745 NETVSC_DRIVER_OBJECT
*Driver
748 DPRINT_ENTER(NETVSC
);
750 DPRINT_DBG(NETVSC
, "sizeof(RNDIS_FILTER_PACKET) == %zd", sizeof(RNDIS_FILTER_PACKET
));
752 Driver
->RequestExtSize
= sizeof(RNDIS_FILTER_PACKET
);
753 Driver
->AdditionalRequestPageBufferCount
= 1; /* For rndis header */
755 /* Driver->Context = rndisDriver; */
757 memset(&gRndisFilter
, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT
));
759 /*rndisDriver->Driver = Driver;
761 ASSERT(Driver->OnLinkStatusChanged);
762 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
764 /* Save the original dispatch handlers before we override it */
765 gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd
= Driver
->Base
.OnDeviceAdd
;
766 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove
= Driver
->Base
.OnDeviceRemove
;
767 gRndisFilter
.InnerDriver
.Base
.OnCleanup
= Driver
->Base
.OnCleanup
;
769 ASSERT(Driver
->OnSend
);
770 ASSERT(Driver
->OnReceiveCallback
);
771 gRndisFilter
.InnerDriver
.OnSend
= Driver
->OnSend
;
772 gRndisFilter
.InnerDriver
.OnReceiveCallback
= Driver
->OnReceiveCallback
;
773 gRndisFilter
.InnerDriver
.OnLinkStatusChanged
= Driver
->OnLinkStatusChanged
;
776 Driver
->Base
.OnDeviceAdd
= RndisFilterOnDeviceAdd
;
777 Driver
->Base
.OnDeviceRemove
= RndisFilterOnDeviceRemove
;
778 Driver
->Base
.OnCleanup
= RndisFilterOnCleanup
;
779 Driver
->OnSend
= RndisFilterOnSend
;
780 Driver
->OnOpen
= RndisFilterOnOpen
;
781 Driver
->OnClose
= RndisFilterOnClose
;
782 /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
783 Driver
->OnReceiveCallback
= RndisFilterOnReceive
;
791 RndisFilterInitDevice(
795 RNDIS_REQUEST
*request
;
796 RNDIS_INITIALIZE_REQUEST
*init
;
797 RNDIS_INITIALIZE_COMPLETE
*initComplete
;
801 DPRINT_ENTER(NETVSC
);
803 request
= GetRndisRequest(Device
, REMOTE_NDIS_INITIALIZE_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST
));
810 /* Setup the rndis set */
811 init
= &request
->RequestMessage
.Message
.InitializeRequest
;
812 init
->MajorVersion
= RNDIS_MAJOR_VERSION
;
813 init
->MinorVersion
= RNDIS_MINOR_VERSION
;
814 init
->MaxTransferSize
= 2048; /* FIXME: Use 1536 - rounded ethernet frame size */
816 Device
->State
= RNDIS_DEV_INITIALIZING
;
818 ret
= RndisFilterSendRequest(Device
, request
);
821 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
825 WaitEventWait(request
->WaitEvent
);
827 initComplete
= &request
->ResponseMessage
.Message
.InitializeComplete
;
828 status
= initComplete
->Status
;
829 if (status
== RNDIS_STATUS_SUCCESS
)
831 Device
->State
= RNDIS_DEV_INITIALIZED
;
836 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
843 PutRndisRequest(Device
, request
);
851 RndisFilterHaltDevice(
855 RNDIS_REQUEST
*request
;
856 RNDIS_HALT_REQUEST
*halt
;
858 DPRINT_ENTER(NETVSC
);
860 /* Attempt to do a rndis device halt */
861 request
= GetRndisRequest(Device
, REMOTE_NDIS_HALT_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST
));
867 /* Setup the rndis set */
868 halt
= &request
->RequestMessage
.Message
.HaltRequest
;
869 halt
->RequestId
= atomic_inc_return(&Device
->NewRequestId
);
871 /* Ignore return since this msg is optional. */
872 RndisFilterSendRequest(Device
, request
);
874 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
879 PutRndisRequest(Device
, request
);
887 RndisFilterOpenDevice(
893 DPRINT_ENTER(NETVSC
);
895 if (Device
->State
!= RNDIS_DEV_INITIALIZED
)
898 ret
= RndisFilterSetPacketFilter(Device
, NDIS_PACKET_TYPE_BROADCAST
|NDIS_PACKET_TYPE_DIRECTED
);
901 Device
->State
= RNDIS_DEV_DATAINITIALIZED
;
909 RndisFilterCloseDevice(
915 DPRINT_ENTER(NETVSC
);
917 if (Device
->State
!= RNDIS_DEV_DATAINITIALIZED
)
920 ret
= RndisFilterSetPacketFilter(Device
, 0);
923 Device
->State
= RNDIS_DEV_INITIALIZED
;
933 RndisFilterOnDeviceAdd(
934 struct hv_device
*Device
,
939 struct NETVSC_DEVICE
*netDevice
;
940 RNDIS_DEVICE
*rndisDevice
;
941 NETVSC_DEVICE_INFO
*deviceInfo
= (NETVSC_DEVICE_INFO
*)AdditionalInfo
;
943 DPRINT_ENTER(NETVSC
);
945 rndisDevice
= GetRndisDevice();
952 DPRINT_DBG(NETVSC
, "rndis device object allocated - %p", rndisDevice
);
954 /* Let the inner driver handle this first to create the netvsc channel */
955 /* NOTE! Once the channel is created, we may get a receive callback */
956 /* (RndisFilterOnReceive()) before this call is completed */
957 ret
= gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd(Device
, AdditionalInfo
);
960 PutRndisDevice(rndisDevice
);
966 /* Initialize the rndis device */
968 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
970 ASSERT(netDevice
->Device
);
972 netDevice
->Extension
= rndisDevice
;
973 rndisDevice
->NetDevice
= netDevice
;
975 /* Send the rndis initialization message */
976 ret
= RndisFilterInitDevice(rndisDevice
);
979 /* TODO: If rndis init failed, we will need to shut down the channel */
982 /* Get the mac address */
983 ret
= RndisFilterQueryDeviceMac(rndisDevice
);
986 /* TODO: shutdown rndis device and the channel */
989 DPRINT_INFO(NETVSC
, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
991 rndisDevice
->HwMacAddr
[0],
992 rndisDevice
->HwMacAddr
[1],
993 rndisDevice
->HwMacAddr
[2],
994 rndisDevice
->HwMacAddr
[3],
995 rndisDevice
->HwMacAddr
[4],
996 rndisDevice
->HwMacAddr
[5]);
998 memcpy(deviceInfo
->MacAddr
, rndisDevice
->HwMacAddr
, HW_MACADDR_LEN
);
1000 RndisFilterQueryDeviceLinkStatus(rndisDevice
);
1002 deviceInfo
->LinkState
= rndisDevice
->LinkStatus
;
1003 DPRINT_INFO(NETVSC
, "Device 0x%p link state %s", rndisDevice
, ((deviceInfo
->LinkState
)?("down"):("up")));
1005 DPRINT_EXIT(NETVSC
);
1012 RndisFilterOnDeviceRemove(
1013 struct hv_device
*Device
1016 struct NETVSC_DEVICE
*netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
1017 RNDIS_DEVICE
*rndisDevice
= (RNDIS_DEVICE
*)netDevice
->Extension
;
1019 DPRINT_ENTER(NETVSC
);
1021 /* Halt and release the rndis device */
1022 RndisFilterHaltDevice(rndisDevice
);
1024 PutRndisDevice(rndisDevice
);
1025 netDevice
->Extension
= NULL
;
1027 /* Pass control to inner driver to remove the device */
1028 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove(Device
);
1030 DPRINT_EXIT(NETVSC
);
1037 RndisFilterOnCleanup(
1038 struct hv_driver
*Driver
1041 DPRINT_ENTER(NETVSC
);
1043 DPRINT_EXIT(NETVSC
);
1048 struct hv_device
*Device
1052 struct NETVSC_DEVICE
*netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
1054 DPRINT_ENTER(NETVSC
);
1057 ret
= RndisFilterOpenDevice((RNDIS_DEVICE
*)netDevice
->Extension
);
1059 DPRINT_EXIT(NETVSC
);
1066 struct hv_device
*Device
1070 struct NETVSC_DEVICE
*netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
1072 DPRINT_ENTER(NETVSC
);
1075 ret
= RndisFilterCloseDevice((RNDIS_DEVICE
*)netDevice
->Extension
);
1077 DPRINT_EXIT(NETVSC
);
1085 struct hv_device
*Device
,
1086 struct hv_netvsc_packet
*Packet
1090 RNDIS_FILTER_PACKET
*filterPacket
;
1091 RNDIS_MESSAGE
*rndisMessage
;
1092 RNDIS_PACKET
*rndisPacket
;
1093 u32 rndisMessageSize
;
1095 DPRINT_ENTER(NETVSC
);
1097 /* Add the rndis header */
1098 filterPacket
= (RNDIS_FILTER_PACKET
*)Packet
->Extension
;
1099 ASSERT(filterPacket
);
1101 memset(filterPacket
, 0, sizeof(RNDIS_FILTER_PACKET
));
1103 rndisMessage
= &filterPacket
->Message
;
1104 rndisMessageSize
= RNDIS_MESSAGE_SIZE(RNDIS_PACKET
);
1106 rndisMessage
->NdisMessageType
= REMOTE_NDIS_PACKET_MSG
;
1107 rndisMessage
->MessageLength
= Packet
->TotalDataBufferLength
+ rndisMessageSize
;
1109 rndisPacket
= &rndisMessage
->Message
.Packet
;
1110 rndisPacket
->DataOffset
= sizeof(RNDIS_PACKET
);
1111 rndisPacket
->DataLength
= Packet
->TotalDataBufferLength
;
1113 Packet
->IsDataPacket
= true;
1114 Packet
->PageBuffers
[0].Pfn
= virt_to_phys(rndisMessage
) >> PAGE_SHIFT
;
1115 Packet
->PageBuffers
[0].Offset
= (unsigned long)rndisMessage
& (PAGE_SIZE
-1);
1116 Packet
->PageBuffers
[0].Length
= rndisMessageSize
;
1118 /* Save the packet send completion and context */
1119 filterPacket
->OnCompletion
= Packet
->Completion
.Send
.OnSendCompletion
;
1120 filterPacket
->CompletionContext
= Packet
->Completion
.Send
.SendCompletionContext
;
1123 Packet
->Completion
.Send
.OnSendCompletion
= RndisFilterOnSendCompletion
;
1124 Packet
->Completion
.Send
.SendCompletionContext
= filterPacket
;
1126 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
, Packet
);
1129 /* Reset the completion to originals to allow retries from above */
1130 Packet
->Completion
.Send
.OnSendCompletion
= filterPacket
->OnCompletion
;
1131 Packet
->Completion
.Send
.SendCompletionContext
= filterPacket
->CompletionContext
;
1134 DPRINT_EXIT(NETVSC
);
1140 RndisFilterOnSendCompletion(
1143 RNDIS_FILTER_PACKET
*filterPacket
= (RNDIS_FILTER_PACKET
*)Context
;
1145 DPRINT_ENTER(NETVSC
);
1147 /* Pass it back to the original handler */
1148 filterPacket
->OnCompletion(filterPacket
->CompletionContext
);
1150 DPRINT_EXIT(NETVSC
);
1155 RndisFilterOnSendRequestCompletion(
1159 DPRINT_ENTER(NETVSC
);
1162 DPRINT_EXIT(NETVSC
);