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>
26 #include <linux/kernel.h>
28 #include "include/logging.h"
30 #include "include/NetVscApi.h"
31 #include "RndisFilter.h"
37 typedef struct _RNDIS_FILTER_DRIVER_OBJECT
{
38 // The original driver
39 NETVSC_DRIVER_OBJECT InnerDriver
;
41 } RNDIS_FILTER_DRIVER_OBJECT
;
44 RNDIS_DEV_UNINITIALIZED
= 0,
45 RNDIS_DEV_INITIALIZING
,
46 RNDIS_DEV_INITIALIZED
,
47 RNDIS_DEV_DATAINITIALIZED
,
50 typedef struct _RNDIS_DEVICE
{
51 NETVSC_DEVICE
*NetDevice
;
53 RNDIS_DEVICE_STATE State
;
58 LIST_ENTRY RequestList
;
60 unsigned char HwMacAddr
[HW_MACADDR_LEN
];
64 typedef struct _RNDIS_REQUEST
{
68 // FIXME: We assumed a fixed size response here. If we do ever need to handle a bigger response,
69 // we can either define a max response message or add a response buffer variable above this field
70 RNDIS_MESSAGE ResponseMessage
;
72 // Simplify allocation by having a netvsc packet inline
75 // FIXME: We assumed a fixed size request here.
76 RNDIS_MESSAGE RequestMessage
;
80 typedef struct _RNDIS_FILTER_PACKET
{
81 void *CompletionContext
;
82 PFN_ON_SENDRECVCOMPLETION OnCompletion
;
84 RNDIS_MESSAGE Message
;
85 } RNDIS_FILTER_PACKET
;
91 RndisFilterSendRequest(
93 RNDIS_REQUEST
*Request
97 RndisFilterReceiveResponse(
99 RNDIS_MESSAGE
*Response
103 RndisFilterReceiveIndicateStatus(
104 RNDIS_DEVICE
*Device
,
105 RNDIS_MESSAGE
*Response
109 RndisFilterReceiveData(
110 RNDIS_DEVICE
*Device
,
111 RNDIS_MESSAGE
*Message
,
112 NETVSC_PACKET
*Packet
116 RndisFilterOnReceive(
117 DEVICE_OBJECT
*Device
,
118 NETVSC_PACKET
*Packet
122 RndisFilterQueryDevice(
123 RNDIS_DEVICE
*Device
,
130 RndisFilterQueryDeviceMac(
135 RndisFilterQueryDeviceLinkStatus(
140 RndisFilterSetPacketFilter(
141 RNDIS_DEVICE
*Device
,
146 RndisFilterInitDevice(
151 RndisFilterOpenDevice(
156 RndisFilterCloseDevice(
161 RndisFilterOnDeviceAdd(
162 DEVICE_OBJECT
*Device
,
167 RndisFilterOnDeviceRemove(
168 DEVICE_OBJECT
*Device
172 RndisFilterOnCleanup(
173 DRIVER_OBJECT
*Driver
178 DEVICE_OBJECT
*Device
183 DEVICE_OBJECT
*Device
188 DEVICE_OBJECT
*Device
,
189 NETVSC_PACKET
*Packet
193 RndisFilterOnSendCompletion(
198 RndisFilterOnSendRequestCompletion(
207 RNDIS_FILTER_DRIVER_OBJECT gRndisFilter
;
209 static inline RNDIS_DEVICE
* GetRndisDevice(void)
211 RNDIS_DEVICE
*device
;
213 device
= kzalloc(sizeof(RNDIS_DEVICE
), GFP_KERNEL
);
219 device
->RequestLock
= SpinlockCreate();
220 if (!device
->RequestLock
)
226 INITIALIZE_LIST_HEAD(&device
->RequestList
);
228 device
->State
= RNDIS_DEV_UNINITIALIZED
;
233 static inline void PutRndisDevice(RNDIS_DEVICE
*Device
)
235 SpinlockClose(Device
->RequestLock
);
239 static inline RNDIS_REQUEST
* GetRndisRequest(RNDIS_DEVICE
*Device
, u32 MessageType
, u32 MessageLength
)
241 RNDIS_REQUEST
*request
;
242 RNDIS_MESSAGE
*rndisMessage
;
243 RNDIS_SET_REQUEST
*set
;
245 request
= kzalloc(sizeof(RNDIS_REQUEST
), GFP_KERNEL
);
251 request
->WaitEvent
= WaitEventCreate();
252 if (!request
->WaitEvent
)
258 rndisMessage
= &request
->RequestMessage
;
259 rndisMessage
->NdisMessageType
= MessageType
;
260 rndisMessage
->MessageLength
= MessageLength
;
262 // Set the request id. This field is always after the rndis header for request/response packet types so
263 // we just used the SetRequest as a template
264 set
= &rndisMessage
->Message
.SetRequest
;
265 set
->RequestId
= InterlockedIncrement((int*)&Device
->NewRequestId
);
267 // Add to the request list
268 SpinlockAcquire(Device
->RequestLock
);
269 INSERT_TAIL_LIST(&Device
->RequestList
, &request
->ListEntry
);
270 SpinlockRelease(Device
->RequestLock
);
275 static inline void PutRndisRequest(RNDIS_DEVICE
*Device
, RNDIS_REQUEST
*Request
)
277 SpinlockAcquire(Device
->RequestLock
);
278 REMOVE_ENTRY_LIST(&Request
->ListEntry
);
279 SpinlockRelease(Device
->RequestLock
);
281 WaitEventClose(Request
->WaitEvent
);
285 static inline void DumpRndisMessage(RNDIS_MESSAGE
*RndisMessage
)
287 switch (RndisMessage
->NdisMessageType
)
289 case REMOTE_NDIS_PACKET_MSG
:
290 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",
291 RndisMessage
->MessageLength
,
292 RndisMessage
->Message
.Packet
.DataOffset
,
293 RndisMessage
->Message
.Packet
.DataLength
,
294 RndisMessage
->Message
.Packet
.NumOOBDataElements
,
295 RndisMessage
->Message
.Packet
.OOBDataOffset
,
296 RndisMessage
->Message
.Packet
.OOBDataLength
,
297 RndisMessage
->Message
.Packet
.PerPacketInfoOffset
,
298 RndisMessage
->Message
.Packet
.PerPacketInfoLength
);
301 case REMOTE_NDIS_INITIALIZE_CMPLT
:
302 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)",
303 RndisMessage
->MessageLength
,
304 RndisMessage
->Message
.InitializeComplete
.RequestId
,
305 RndisMessage
->Message
.InitializeComplete
.Status
,
306 RndisMessage
->Message
.InitializeComplete
.MajorVersion
,
307 RndisMessage
->Message
.InitializeComplete
.MinorVersion
,
308 RndisMessage
->Message
.InitializeComplete
.DeviceFlags
,
309 RndisMessage
->Message
.InitializeComplete
.MaxTransferSize
,
310 RndisMessage
->Message
.InitializeComplete
.MaxPacketsPerMessage
,
311 RndisMessage
->Message
.InitializeComplete
.PacketAlignmentFactor
);
314 case REMOTE_NDIS_QUERY_CMPLT
:
315 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_QUERY_CMPLT (len %u, id 0x%x, status 0x%x, buf len %u, buf offset %u)",
316 RndisMessage
->MessageLength
,
317 RndisMessage
->Message
.QueryComplete
.RequestId
,
318 RndisMessage
->Message
.QueryComplete
.Status
,
319 RndisMessage
->Message
.QueryComplete
.InformationBufferLength
,
320 RndisMessage
->Message
.QueryComplete
.InformationBufferOffset
);
323 case REMOTE_NDIS_SET_CMPLT
:
324 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
325 RndisMessage
->MessageLength
,
326 RndisMessage
->Message
.SetComplete
.RequestId
,
327 RndisMessage
->Message
.SetComplete
.Status
);
330 case REMOTE_NDIS_INDICATE_STATUS_MSG
:
331 DPRINT_DBG(NETVSC
, "REMOTE_NDIS_INDICATE_STATUS_MSG (len %u, status 0x%x, buf len %u, buf offset %u)",
332 RndisMessage
->MessageLength
,
333 RndisMessage
->Message
.IndicateStatus
.Status
,
334 RndisMessage
->Message
.IndicateStatus
.StatusBufferLength
,
335 RndisMessage
->Message
.IndicateStatus
.StatusBufferOffset
);
339 DPRINT_DBG(NETVSC
, "0x%x (len %u)",
340 RndisMessage
->NdisMessageType
,
341 RndisMessage
->MessageLength
);
347 RndisFilterSendRequest(
348 RNDIS_DEVICE
*Device
,
349 RNDIS_REQUEST
*Request
353 NETVSC_PACKET
*packet
;
355 DPRINT_ENTER(NETVSC
);
357 // Setup the packet to send it
358 packet
= &Request
->Packet
;
360 packet
->IsDataPacket
= false;
361 packet
->TotalDataBufferLength
= Request
->RequestMessage
.MessageLength
;
362 packet
->PageBufferCount
= 1;
364 packet
->PageBuffers
[0].Pfn
= GetPhysicalAddress(&Request
->RequestMessage
) >> PAGE_SHIFT
;
365 packet
->PageBuffers
[0].Length
= Request
->RequestMessage
.MessageLength
;
366 packet
->PageBuffers
[0].Offset
= (unsigned long)&Request
->RequestMessage
& (PAGE_SIZE
-1);
368 packet
->Completion
.Send
.SendCompletionContext
= Request
;//packet;
369 packet
->Completion
.Send
.OnSendCompletion
= RndisFilterOnSendRequestCompletion
;
370 packet
->Completion
.Send
.SendCompletionTid
= (unsigned long)Device
;
372 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
->NetDevice
->Device
, packet
);
379 RndisFilterReceiveResponse(
380 RNDIS_DEVICE
*Device
,
381 RNDIS_MESSAGE
*Response
386 RNDIS_REQUEST
*request
=NULL
;
389 DPRINT_ENTER(NETVSC
);
391 SpinlockAcquire(Device
->RequestLock
);
392 ITERATE_LIST_ENTRIES(anchor
, curr
, &Device
->RequestList
)
394 request
= CONTAINING_RECORD(curr
, RNDIS_REQUEST
, ListEntry
);
396 // All request/response message contains RequestId as the 1st field
397 if (request
->RequestMessage
.Message
.InitializeRequest
.RequestId
== Response
->Message
.InitializeComplete
.RequestId
)
399 DPRINT_DBG(NETVSC
, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
400 request
->RequestMessage
.Message
.InitializeRequest
.RequestId
, request
->RequestMessage
.NdisMessageType
, Response
->NdisMessageType
);
406 SpinlockRelease(Device
->RequestLock
);
410 if (Response
->MessageLength
<= sizeof(RNDIS_MESSAGE
))
412 memcpy(&request
->ResponseMessage
, Response
, Response
->MessageLength
);
416 DPRINT_ERR(NETVSC
, "rndis response buffer overflow detected (size %u max %u)", Response
->MessageLength
, sizeof(RNDIS_FILTER_PACKET
));
418 if (Response
->NdisMessageType
== REMOTE_NDIS_RESET_CMPLT
) // does not have a request id field
420 request
->ResponseMessage
.Message
.ResetComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
424 request
->ResponseMessage
.Message
.InitializeComplete
.Status
= STATUS_BUFFER_OVERFLOW
;
428 WaitEventSet(request
->WaitEvent
);
432 DPRINT_ERR(NETVSC
, "no rndis request found for this response (id 0x%x res type 0x%x)",
433 Response
->Message
.InitializeComplete
.RequestId
, Response
->NdisMessageType
);
440 RndisFilterReceiveIndicateStatus(
441 RNDIS_DEVICE
*Device
,
442 RNDIS_MESSAGE
*Response
445 RNDIS_INDICATE_STATUS
*indicate
= &Response
->Message
.IndicateStatus
;
447 if (indicate
->Status
== RNDIS_STATUS_MEDIA_CONNECT
)
449 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 1);
451 else if (indicate
->Status
== RNDIS_STATUS_MEDIA_DISCONNECT
)
453 gRndisFilter
.InnerDriver
.OnLinkStatusChanged(Device
->NetDevice
->Device
, 0);
462 RndisFilterReceiveData(
463 RNDIS_DEVICE
*Device
,
464 RNDIS_MESSAGE
*Message
,
465 NETVSC_PACKET
*Packet
468 RNDIS_PACKET
*rndisPacket
;
471 DPRINT_ENTER(NETVSC
);
473 // empty ethernet frame ??
474 ASSERT(Packet
->PageBuffers
[0].Length
> RNDIS_MESSAGE_SIZE(RNDIS_PACKET
));
476 rndisPacket
= &Message
->Message
.Packet
;
478 // FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
479 // netvsc packet (ie TotalDataBufferLength != MessageLength)
481 // Remove the rndis header and pass it back up the stack
482 dataOffset
= RNDIS_HEADER_SIZE
+ rndisPacket
->DataOffset
;
484 Packet
->TotalDataBufferLength
-= dataOffset
;
485 Packet
->PageBuffers
[0].Offset
+= dataOffset
;
486 Packet
->PageBuffers
[0].Length
-= dataOffset
;
488 Packet
->IsDataPacket
= true;
490 gRndisFilter
.InnerDriver
.OnReceiveCallback(Device
->NetDevice
->Device
, Packet
);
496 RndisFilterOnReceive(
497 DEVICE_OBJECT
*Device
,
498 NETVSC_PACKET
*Packet
501 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
502 RNDIS_DEVICE
*rndisDevice
;
503 RNDIS_MESSAGE rndisMessage
;
504 RNDIS_MESSAGE
*rndisHeader
;
506 DPRINT_ENTER(NETVSC
);
509 //Make sure the rndis device state is initialized
510 if (!netDevice
->Extension
)
512 DPRINT_ERR(NETVSC
, "got rndis message but no rndis device...dropping this message!");
517 rndisDevice
= (RNDIS_DEVICE
*)netDevice
->Extension
;
518 if (rndisDevice
->State
== RNDIS_DEV_UNINITIALIZED
)
520 DPRINT_ERR(NETVSC
, "got rndis message but rndis device uninitialized...dropping this message!");
525 rndisHeader
= (RNDIS_MESSAGE
*)PageMapVirtualAddress(Packet
->PageBuffers
[0].Pfn
);
527 rndisHeader
= (void*)((unsigned long)rndisHeader
+ Packet
->PageBuffers
[0].Offset
);
529 // Make sure we got a valid rndis message
530 // FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but
531 // the ByteCount field in the xfer page range shows 52 bytes
533 if ( Packet
->TotalDataBufferLength
!= rndisHeader
->MessageLength
)
535 PageUnmapVirtualAddress((void*)(unsigned long)rndisHeader
- Packet
->PageBuffers
[0].Offset
);
537 DPRINT_ERR(NETVSC
, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
538 rndisHeader
->MessageLength
, Packet
->TotalDataBufferLength
);
544 if ((rndisHeader
->NdisMessageType
!= REMOTE_NDIS_PACKET_MSG
) && (rndisHeader
->MessageLength
> sizeof(RNDIS_MESSAGE
)))
546 DPRINT_ERR(NETVSC
, "incoming rndis message buffer overflow detected (got %u, max %u)...marking it an error!",
547 rndisHeader
->MessageLength
, sizeof(RNDIS_MESSAGE
));
550 memcpy(&rndisMessage
, rndisHeader
, (rndisHeader
->MessageLength
> sizeof(RNDIS_MESSAGE
))?sizeof(RNDIS_MESSAGE
):rndisHeader
->MessageLength
);
552 PageUnmapVirtualAddress((void*)(unsigned long)rndisHeader
- Packet
->PageBuffers
[0].Offset
);
554 DumpRndisMessage(&rndisMessage
);
556 switch (rndisMessage
.NdisMessageType
)
559 case REMOTE_NDIS_PACKET_MSG
:
560 RndisFilterReceiveData(rndisDevice
, &rndisMessage
, Packet
);
564 case REMOTE_NDIS_INITIALIZE_CMPLT
:
565 case REMOTE_NDIS_QUERY_CMPLT
:
566 case REMOTE_NDIS_SET_CMPLT
:
567 //case REMOTE_NDIS_RESET_CMPLT:
568 //case REMOTE_NDIS_KEEPALIVE_CMPLT:
569 RndisFilterReceiveResponse(rndisDevice
, &rndisMessage
);
573 case REMOTE_NDIS_INDICATE_STATUS_MSG
:
574 RndisFilterReceiveIndicateStatus(rndisDevice
, &rndisMessage
);
577 DPRINT_ERR(NETVSC
, "unhandled rndis message (type %u len %u)", rndisMessage
.NdisMessageType
, rndisMessage
.MessageLength
);
587 RndisFilterQueryDevice(
588 RNDIS_DEVICE
*Device
,
594 RNDIS_REQUEST
*request
;
595 u32 inresultSize
= *ResultSize
;
596 RNDIS_QUERY_REQUEST
*query
;
597 RNDIS_QUERY_COMPLETE
*queryComplete
;
600 DPRINT_ENTER(NETVSC
);
605 request
= GetRndisRequest(Device
, REMOTE_NDIS_QUERY_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST
));
612 // Setup the rndis query
613 query
= &request
->RequestMessage
.Message
.QueryRequest
;
615 query
->InformationBufferOffset
= sizeof(RNDIS_QUERY_REQUEST
);
616 query
->InformationBufferLength
= 0;
617 query
->DeviceVcHandle
= 0;
619 ret
= RndisFilterSendRequest(Device
, request
);
625 WaitEventWait(request
->WaitEvent
);
627 // Copy the response back
628 queryComplete
= &request
->ResponseMessage
.Message
.QueryComplete
;
630 if (queryComplete
->InformationBufferLength
> inresultSize
)
637 (void*)((unsigned long)queryComplete
+ queryComplete
->InformationBufferOffset
),
638 queryComplete
->InformationBufferLength
);
640 *ResultSize
= queryComplete
->InformationBufferLength
;
645 PutRndisRequest(Device
, request
);
653 RndisFilterQueryDeviceMac(
657 u32 size
=HW_MACADDR_LEN
;
659 return RndisFilterQueryDevice(Device
,
660 RNDIS_OID_802_3_PERMANENT_ADDRESS
,
666 RndisFilterQueryDeviceLinkStatus(
670 u32 size
=sizeof(u32
);
672 return RndisFilterQueryDevice(Device
,
673 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS
,
679 RndisFilterSetPacketFilter(
680 RNDIS_DEVICE
*Device
,
684 RNDIS_REQUEST
*request
;
685 RNDIS_SET_REQUEST
*set
;
686 RNDIS_SET_COMPLETE
*setComplete
;
690 DPRINT_ENTER(NETVSC
);
692 ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST
) + sizeof(u32
) <= sizeof(RNDIS_MESSAGE
));
694 request
= GetRndisRequest(Device
, REMOTE_NDIS_SET_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST
) + sizeof(u32
));
701 // Setup the rndis set
702 set
= &request
->RequestMessage
.Message
.SetRequest
;
703 set
->Oid
= RNDIS_OID_GEN_CURRENT_PACKET_FILTER
;
704 set
->InformationBufferLength
= sizeof(u32
);
705 set
->InformationBufferOffset
= sizeof(RNDIS_SET_REQUEST
);
707 memcpy((void*)(unsigned long)set
+ sizeof(RNDIS_SET_REQUEST
), &NewFilter
, sizeof(u32
));
709 ret
= RndisFilterSendRequest(Device
, request
);
715 ret
= WaitEventWaitEx(request
->WaitEvent
, 2000/*2sec*/);
719 DPRINT_ERR(NETVSC
, "timeout before we got a set response...");
720 // We cant deallocate the request since we may still receive a send completion for it.
729 setComplete
= &request
->ResponseMessage
.Message
.SetComplete
;
730 status
= setComplete
->Status
;
736 PutRndisRequest(Device
, request
);
746 NETVSC_DRIVER_OBJECT
*Driver
749 DPRINT_ENTER(NETVSC
);
751 DPRINT_DBG(NETVSC
, "sizeof(RNDIS_FILTER_PACKET) == %d", sizeof(RNDIS_FILTER_PACKET
));
753 Driver
->RequestExtSize
= sizeof(RNDIS_FILTER_PACKET
);
754 Driver
->AdditionalRequestPageBufferCount
= 1; // For rndis header
756 //Driver->Context = rndisDriver;
758 memset(&gRndisFilter
, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT
));
760 /*rndisDriver->Driver = Driver;
762 ASSERT(Driver->OnLinkStatusChanged);
763 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
765 // Save the original dispatch handlers before we override it
766 gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd
= Driver
->Base
.OnDeviceAdd
;
767 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove
= Driver
->Base
.OnDeviceRemove
;
768 gRndisFilter
.InnerDriver
.Base
.OnCleanup
= Driver
->Base
.OnCleanup
;
770 ASSERT(Driver
->OnSend
);
771 ASSERT(Driver
->OnReceiveCallback
);
772 gRndisFilter
.InnerDriver
.OnSend
= Driver
->OnSend
;
773 gRndisFilter
.InnerDriver
.OnReceiveCallback
= Driver
->OnReceiveCallback
;
774 gRndisFilter
.InnerDriver
.OnLinkStatusChanged
= Driver
->OnLinkStatusChanged
;
777 Driver
->Base
.OnDeviceAdd
= RndisFilterOnDeviceAdd
;
778 Driver
->Base
.OnDeviceRemove
= RndisFilterOnDeviceRemove
;
779 Driver
->Base
.OnCleanup
= RndisFilterOnCleanup
;
780 Driver
->OnSend
= RndisFilterOnSend
;
781 Driver
->OnOpen
= RndisFilterOnOpen
;
782 Driver
->OnClose
= RndisFilterOnClose
;
783 //Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus;
784 Driver
->OnReceiveCallback
= RndisFilterOnReceive
;
792 RndisFilterInitDevice(
796 RNDIS_REQUEST
*request
;
797 RNDIS_INITIALIZE_REQUEST
*init
;
798 RNDIS_INITIALIZE_COMPLETE
*initComplete
;
802 DPRINT_ENTER(NETVSC
);
804 request
= GetRndisRequest(Device
, REMOTE_NDIS_INITIALIZE_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST
));
811 // Setup the rndis set
812 init
= &request
->RequestMessage
.Message
.InitializeRequest
;
813 init
->MajorVersion
= RNDIS_MAJOR_VERSION
;
814 init
->MinorVersion
= RNDIS_MINOR_VERSION
;
815 init
->MaxTransferSize
= 2048; // FIXME: Use 1536 - rounded ethernet frame size
817 Device
->State
= RNDIS_DEV_INITIALIZING
;
819 ret
= RndisFilterSendRequest(Device
, request
);
822 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
826 WaitEventWait(request
->WaitEvent
);
828 initComplete
= &request
->ResponseMessage
.Message
.InitializeComplete
;
829 status
= initComplete
->Status
;
830 if (status
== RNDIS_STATUS_SUCCESS
)
832 Device
->State
= RNDIS_DEV_INITIALIZED
;
837 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
844 PutRndisRequest(Device
, request
);
852 RndisFilterHaltDevice(
856 RNDIS_REQUEST
*request
;
857 RNDIS_HALT_REQUEST
*halt
;
859 DPRINT_ENTER(NETVSC
);
861 // Attempt to do a rndis device halt
862 request
= GetRndisRequest(Device
, REMOTE_NDIS_HALT_MSG
, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST
));
868 // Setup the rndis set
869 halt
= &request
->RequestMessage
.Message
.HaltRequest
;
870 halt
->RequestId
= InterlockedIncrement((int*)&Device
->NewRequestId
);
872 // Ignore return since this msg is optional.
873 RndisFilterSendRequest(Device
, request
);
875 Device
->State
= RNDIS_DEV_UNINITIALIZED
;
880 PutRndisRequest(Device
, request
);
888 RndisFilterOpenDevice(
894 DPRINT_ENTER(NETVSC
);
896 if (Device
->State
!= RNDIS_DEV_INITIALIZED
)
899 ret
= RndisFilterSetPacketFilter(Device
, NDIS_PACKET_TYPE_BROADCAST
|NDIS_PACKET_TYPE_DIRECTED
);
902 Device
->State
= RNDIS_DEV_DATAINITIALIZED
;
910 RndisFilterCloseDevice(
916 DPRINT_ENTER(NETVSC
);
918 if (Device
->State
!= RNDIS_DEV_DATAINITIALIZED
)
921 ret
= RndisFilterSetPacketFilter(Device
, 0);
924 Device
->State
= RNDIS_DEV_INITIALIZED
;
934 RndisFilterOnDeviceAdd(
935 DEVICE_OBJECT
*Device
,
940 NETVSC_DEVICE
*netDevice
;
941 RNDIS_DEVICE
*rndisDevice
;
942 NETVSC_DEVICE_INFO
*deviceInfo
= (NETVSC_DEVICE_INFO
*)AdditionalInfo
;
944 DPRINT_ENTER(NETVSC
);
946 rndisDevice
= GetRndisDevice();
953 DPRINT_DBG(NETVSC
, "rndis device object allocated - %p", rndisDevice
);
955 // Let the inner driver handle this first to create the netvsc channel
956 // NOTE! Once the channel is created, we may get a receive callback
957 // (RndisFilterOnReceive()) before this call is completed
958 ret
= gRndisFilter
.InnerDriver
.Base
.OnDeviceAdd(Device
, AdditionalInfo
);
961 PutRndisDevice(rndisDevice
);
967 // Initialize the rndis device
969 netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
971 ASSERT(netDevice
->Device
);
973 netDevice
->Extension
= rndisDevice
;
974 rndisDevice
->NetDevice
= netDevice
;
976 // Send the rndis initialization message
977 ret
= RndisFilterInitDevice(rndisDevice
);
980 // TODO: If rndis init failed, we will need to shut down the channel
983 // Get the mac address
984 ret
= RndisFilterQueryDeviceMac(rndisDevice
);
987 // TODO: shutdown rndis device and the channel
990 DPRINT_INFO(NETVSC
, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
992 rndisDevice
->HwMacAddr
[0],
993 rndisDevice
->HwMacAddr
[1],
994 rndisDevice
->HwMacAddr
[2],
995 rndisDevice
->HwMacAddr
[3],
996 rndisDevice
->HwMacAddr
[4],
997 rndisDevice
->HwMacAddr
[5]);
999 memcpy(deviceInfo
->MacAddr
, rndisDevice
->HwMacAddr
, HW_MACADDR_LEN
);
1001 RndisFilterQueryDeviceLinkStatus(rndisDevice
);
1003 deviceInfo
->LinkState
= rndisDevice
->LinkStatus
;
1004 DPRINT_INFO(NETVSC
, "Device 0x%p link state %s", rndisDevice
, ((deviceInfo
->LinkState
)?("down"):("up")));
1006 DPRINT_EXIT(NETVSC
);
1013 RndisFilterOnDeviceRemove(
1014 DEVICE_OBJECT
*Device
1017 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
1018 RNDIS_DEVICE
*rndisDevice
= (RNDIS_DEVICE
*)netDevice
->Extension
;
1020 DPRINT_ENTER(NETVSC
);
1022 // Halt and release the rndis device
1023 RndisFilterHaltDevice(rndisDevice
);
1025 PutRndisDevice(rndisDevice
);
1026 netDevice
->Extension
= NULL
;
1028 // Pass control to inner driver to remove the device
1029 gRndisFilter
.InnerDriver
.Base
.OnDeviceRemove(Device
);
1031 DPRINT_EXIT(NETVSC
);
1038 RndisFilterOnCleanup(
1039 DRIVER_OBJECT
*Driver
1042 DPRINT_ENTER(NETVSC
);
1044 DPRINT_EXIT(NETVSC
);
1049 DEVICE_OBJECT
*Device
1053 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
1055 DPRINT_ENTER(NETVSC
);
1058 ret
= RndisFilterOpenDevice((RNDIS_DEVICE
*)netDevice
->Extension
);
1060 DPRINT_EXIT(NETVSC
);
1067 DEVICE_OBJECT
*Device
1071 NETVSC_DEVICE
*netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
1073 DPRINT_ENTER(NETVSC
);
1076 ret
= RndisFilterCloseDevice((RNDIS_DEVICE
*)netDevice
->Extension
);
1078 DPRINT_EXIT(NETVSC
);
1086 DEVICE_OBJECT
*Device
,
1087 NETVSC_PACKET
*Packet
1091 RNDIS_FILTER_PACKET
*filterPacket
;
1092 RNDIS_MESSAGE
*rndisMessage
;
1093 RNDIS_PACKET
*rndisPacket
;
1094 u32 rndisMessageSize
;
1096 DPRINT_ENTER(NETVSC
);
1098 // Add the rndis header
1099 filterPacket
= (RNDIS_FILTER_PACKET
*)Packet
->Extension
;
1100 ASSERT(filterPacket
);
1102 memset(filterPacket
, 0, sizeof(RNDIS_FILTER_PACKET
));
1104 rndisMessage
= &filterPacket
->Message
;
1105 rndisMessageSize
= RNDIS_MESSAGE_SIZE(RNDIS_PACKET
);
1107 rndisMessage
->NdisMessageType
= REMOTE_NDIS_PACKET_MSG
;
1108 rndisMessage
->MessageLength
= Packet
->TotalDataBufferLength
+ rndisMessageSize
;
1110 rndisPacket
= &rndisMessage
->Message
.Packet
;
1111 rndisPacket
->DataOffset
= sizeof(RNDIS_PACKET
);
1112 rndisPacket
->DataLength
= Packet
->TotalDataBufferLength
;
1114 Packet
->IsDataPacket
= true;
1115 Packet
->PageBuffers
[0].Pfn
= GetPhysicalAddress(rndisMessage
) >> PAGE_SHIFT
;
1116 Packet
->PageBuffers
[0].Offset
= (unsigned long)rndisMessage
& (PAGE_SIZE
-1);
1117 Packet
->PageBuffers
[0].Length
= rndisMessageSize
;
1119 // Save the packet send completion and context
1120 filterPacket
->OnCompletion
= Packet
->Completion
.Send
.OnSendCompletion
;
1121 filterPacket
->CompletionContext
= Packet
->Completion
.Send
.SendCompletionContext
;
1124 Packet
->Completion
.Send
.OnSendCompletion
= RndisFilterOnSendCompletion
;
1125 Packet
->Completion
.Send
.SendCompletionContext
= filterPacket
;
1127 ret
= gRndisFilter
.InnerDriver
.OnSend(Device
, Packet
);
1130 // Reset the completion to originals to allow retries from above
1131 Packet
->Completion
.Send
.OnSendCompletion
= filterPacket
->OnCompletion
;
1132 Packet
->Completion
.Send
.SendCompletionContext
= filterPacket
->CompletionContext
;
1135 DPRINT_EXIT(NETVSC
);
1141 RndisFilterOnSendCompletion(
1144 RNDIS_FILTER_PACKET
*filterPacket
= (RNDIS_FILTER_PACKET
*)Context
;
1146 DPRINT_ENTER(NETVSC
);
1148 // Pass it back to the original handler
1149 filterPacket
->OnCompletion(filterPacket
->CompletionContext
);
1151 DPRINT_EXIT(NETVSC
);
1156 RndisFilterOnSendRequestCompletion(
1160 DPRINT_ENTER(NETVSC
);
1163 DPRINT_EXIT(NETVSC
);