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>
31 #include "NetVscApi.h"
32 #include "RndisFilter.h"
38 typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
39 /* The original driver */
40 struct netvsc_driver 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 struct rndis_message ResponseMessage;
73 /* Simplify allocation by having a netvsc packet inline */
74 struct hv_netvsc_packet Packet;
75 struct hv_page_buffer Buffer;
76 /* FIXME: We assumed a fixed size request here. */
77 struct rndis_message RequestMessage;
81 typedef struct _RNDIS_FILTER_PACKET {
82 void *CompletionContext;
83 PFN_ON_SENDRECVCOMPLETION OnCompletion;
85 struct rndis_message Message;
86 } RNDIS_FILTER_PACKET;
89 /* Internal routines */
92 RndisFilterSendRequest(
94 RNDIS_REQUEST *Request
97 static void RndisFilterReceiveResponse(RNDIS_DEVICE *Device,
98 struct rndis_message *Response);
100 static void RndisFilterReceiveIndicateStatus(RNDIS_DEVICE *Device,
101 struct rndis_message *Response);
103 static void RndisFilterReceiveData(RNDIS_DEVICE *Device,
104 struct rndis_message *Message,
105 struct hv_netvsc_packet *Packet);
107 static int RndisFilterOnReceive(
108 struct hv_device *Device,
109 struct hv_netvsc_packet *Packet
113 RndisFilterQueryDevice(
114 RNDIS_DEVICE *Device,
121 RndisFilterQueryDeviceMac(
126 RndisFilterQueryDeviceLinkStatus(
131 RndisFilterSetPacketFilter(
132 RNDIS_DEVICE *Device,
137 RndisFilterInitDevice(
142 RndisFilterOpenDevice(
147 RndisFilterCloseDevice(
152 RndisFilterOnDeviceAdd(
153 struct hv_device *Device,
158 RndisFilterOnDeviceRemove(
159 struct hv_device *Device
163 RndisFilterOnCleanup(
164 struct hv_driver *Driver
169 struct hv_device *Device
174 struct hv_device *Device
179 struct hv_device *Device,
180 struct hv_netvsc_packet *Packet
184 RndisFilterOnSendCompletion(
189 RndisFilterOnSendRequestCompletion(
197 /* The one and only */
198 static RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
200 static inline RNDIS_DEVICE* GetRndisDevice(void)
202 RNDIS_DEVICE *device;
204 device = kzalloc(sizeof(RNDIS_DEVICE), GFP_KERNEL);
210 spin_lock_init(&device->request_lock);
212 INITIALIZE_LIST_HEAD(&device->RequestList);
214 device->State = RNDIS_DEV_UNINITIALIZED;
219 static inline void PutRndisDevice(RNDIS_DEVICE *Device)
224 static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, u32 MessageType, u32 MessageLength)
226 RNDIS_REQUEST *request;
227 struct rndis_message *rndisMessage;
228 struct rndis_set_request *set;
231 request = kzalloc(sizeof(RNDIS_REQUEST), GFP_KERNEL);
237 request->WaitEvent = osd_WaitEventCreate();
238 if (!request->WaitEvent)
244 rndisMessage = &request->RequestMessage;
245 rndisMessage->NdisMessageType = MessageType;
246 rndisMessage->MessageLength = MessageLength;
248 /* Set the request id. This field is always after the rndis header for request/response packet types so */
249 /* we just used the SetRequest as a template */
250 set = &rndisMessage->Message.SetRequest;
251 set->RequestId = atomic_inc_return(&Device->NewRequestId);
253 /* Add to the request list */
254 spin_lock_irqsave(&Device->request_lock, flags);
255 INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
256 spin_unlock_irqrestore(&Device->request_lock, flags);
261 static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
265 spin_lock_irqsave(&Device->request_lock, flags);
266 REMOVE_ENTRY_LIST(&Request->ListEntry);
267 spin_unlock_irqrestore(&Device->request_lock, flags);
269 kfree(Request->WaitEvent);
273 static inline void DumpRndisMessage(struct rndis_message *RndisMessage)
275 switch (RndisMessage->NdisMessageType)
277 case REMOTE_NDIS_PACKET_MSG:
278 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",
279 RndisMessage->MessageLength,
280 RndisMessage->Message.Packet.DataOffset,
281 RndisMessage->Message.Packet.DataLength,
282 RndisMessage->Message.Packet.NumOOBDataElements,
283 RndisMessage->Message.Packet.OOBDataOffset,
284 RndisMessage->Message.Packet.OOBDataLength,
285 RndisMessage->Message.Packet.PerPacketInfoOffset,
286 RndisMessage->Message.Packet.PerPacketInfoLength);
289 case REMOTE_NDIS_INITIALIZE_CMPLT:
290 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)",
291 RndisMessage->MessageLength,
292 RndisMessage->Message.InitializeComplete.RequestId,
293 RndisMessage->Message.InitializeComplete.Status,
294 RndisMessage->Message.InitializeComplete.MajorVersion,
295 RndisMessage->Message.InitializeComplete.MinorVersion,
296 RndisMessage->Message.InitializeComplete.DeviceFlags,
297 RndisMessage->Message.InitializeComplete.MaxTransferSize,
298 RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
299 RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
302 case REMOTE_NDIS_QUERY_CMPLT:
303 DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT (len %u, id 0x%x, status 0x%x, buf len %u, buf offset %u)",
304 RndisMessage->MessageLength,
305 RndisMessage->Message.QueryComplete.RequestId,
306 RndisMessage->Message.QueryComplete.Status,
307 RndisMessage->Message.QueryComplete.InformationBufferLength,
308 RndisMessage->Message.QueryComplete.InformationBufferOffset);
311 case REMOTE_NDIS_SET_CMPLT:
312 DPRINT_DBG(NETVSC, "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
313 RndisMessage->MessageLength,
314 RndisMessage->Message.SetComplete.RequestId,
315 RndisMessage->Message.SetComplete.Status);
318 case REMOTE_NDIS_INDICATE_STATUS_MSG:
319 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG (len %u, status 0x%x, buf len %u, buf offset %u)",
320 RndisMessage->MessageLength,
321 RndisMessage->Message.IndicateStatus.Status,
322 RndisMessage->Message.IndicateStatus.StatusBufferLength,
323 RndisMessage->Message.IndicateStatus.StatusBufferOffset);
327 DPRINT_DBG(NETVSC, "0x%x (len %u)",
328 RndisMessage->NdisMessageType,
329 RndisMessage->MessageLength);
335 RndisFilterSendRequest(
336 RNDIS_DEVICE *Device,
337 RNDIS_REQUEST *Request
341 struct hv_netvsc_packet *packet;
343 DPRINT_ENTER(NETVSC);
345 /* Setup the packet to send it */
346 packet = &Request->Packet;
348 packet->IsDataPacket = false;
349 packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
350 packet->PageBufferCount = 1;
352 packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >> PAGE_SHIFT;
353 packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
354 packet->PageBuffers[0].Offset = (unsigned long)&Request->RequestMessage & (PAGE_SIZE -1);
356 packet->Completion.Send.SendCompletionContext = Request;/* packet; */
357 packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
358 packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
360 ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
366 static void RndisFilterReceiveResponse(RNDIS_DEVICE *Device,
367 struct rndis_message *Response)
371 RNDIS_REQUEST *request=NULL;
375 DPRINT_ENTER(NETVSC);
377 spin_lock_irqsave(&Device->request_lock, flags);
378 ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList)
380 request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
382 /* All request/response message contains RequestId as the 1st field */
383 if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
385 DPRINT_DBG(NETVSC, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
386 request->RequestMessage.Message.InitializeRequest.RequestId, request->RequestMessage.NdisMessageType, Response->NdisMessageType);
392 spin_unlock_irqrestore(&Device->request_lock, flags);
396 if (Response->MessageLength <= sizeof(struct rndis_message))
398 memcpy(&request->ResponseMessage, Response, Response->MessageLength);
402 DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %zu)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
404 if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) /* does not have a request id field */
406 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
410 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
414 osd_WaitEventSet(request->WaitEvent);
418 DPRINT_ERR(NETVSC, "no rndis request found for this response (id 0x%x res type 0x%x)",
419 Response->Message.InitializeComplete.RequestId, Response->NdisMessageType);
425 static void RndisFilterReceiveIndicateStatus(RNDIS_DEVICE *Device,
426 struct rndis_message *Response)
428 struct rndis_indicate_status *indicate = &Response->Message.IndicateStatus;
430 if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT)
432 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
434 else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT)
436 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
444 static void RndisFilterReceiveData(RNDIS_DEVICE *Device,
445 struct rndis_message *Message,
446 struct hv_netvsc_packet *Packet)
448 struct rndis_packet *rndisPacket;
451 DPRINT_ENTER(NETVSC);
453 /* empty ethernet frame ?? */
454 ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(struct rndis_packet));
456 rndisPacket = &Message->Message.Packet;
458 /* FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this */
459 /* netvsc packet (ie TotalDataBufferLength != MessageLength) */
461 /* Remove the rndis header and pass it back up the stack */
462 dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
464 Packet->TotalDataBufferLength -= dataOffset;
465 Packet->PageBuffers[0].Offset += dataOffset;
466 Packet->PageBuffers[0].Length -= dataOffset;
468 Packet->IsDataPacket = true;
470 gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device, Packet);
476 RndisFilterOnReceive(
477 struct hv_device *Device,
478 struct hv_netvsc_packet *Packet
481 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
482 RNDIS_DEVICE *rndisDevice;
483 struct rndis_message rndisMessage;
484 struct rndis_message *rndisHeader;
486 DPRINT_ENTER(NETVSC);
489 /* Make sure the rndis device state is initialized */
490 if (!netDevice->Extension)
492 DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
497 rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
498 if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED)
500 DPRINT_ERR(NETVSC, "got rndis message but rndis device uninitialized...dropping this message!");
505 rndisHeader = (struct rndis_message *)kmap_atomic(pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
507 rndisHeader = (void*)((unsigned long)rndisHeader + Packet->PageBuffers[0].Offset);
509 /* Make sure we got a valid rndis message */
510 /* FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but */
511 /* the ByteCount field in the xfer page range shows 52 bytes */
513 if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
515 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
517 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
518 rndisHeader->MessageLength, Packet->TotalDataBufferLength);
524 if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(struct rndis_message)))
526 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %zu)...marking it an error!",
527 rndisHeader->MessageLength, sizeof(struct rndis_message));
530 memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(struct rndis_message))?sizeof(struct rndis_message):rndisHeader->MessageLength);
532 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
534 DumpRndisMessage(&rndisMessage);
536 switch (rndisMessage.NdisMessageType)
539 case REMOTE_NDIS_PACKET_MSG:
540 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
543 /* completion msgs */
544 case REMOTE_NDIS_INITIALIZE_CMPLT:
545 case REMOTE_NDIS_QUERY_CMPLT:
546 case REMOTE_NDIS_SET_CMPLT:
547 /* case REMOTE_NDIS_RESET_CMPLT: */
548 /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
549 RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
552 /* notification msgs */
553 case REMOTE_NDIS_INDICATE_STATUS_MSG:
554 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
557 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", rndisMessage.NdisMessageType, rndisMessage.MessageLength);
567 RndisFilterQueryDevice(
568 RNDIS_DEVICE *Device,
574 RNDIS_REQUEST *request;
575 u32 inresultSize = *ResultSize;
576 struct rndis_query_request *query;
577 struct rndis_query_complete *queryComplete;
580 DPRINT_ENTER(NETVSC);
585 request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(struct rndis_query_request));
592 /* Setup the rndis query */
593 query = &request->RequestMessage.Message.QueryRequest;
595 query->InformationBufferOffset = sizeof(struct rndis_query_request);
596 query->InformationBufferLength = 0;
597 query->DeviceVcHandle = 0;
599 ret = RndisFilterSendRequest(Device, request);
605 osd_WaitEventWait(request->WaitEvent);
607 /* Copy the response back */
608 queryComplete = &request->ResponseMessage.Message.QueryComplete;
610 if (queryComplete->InformationBufferLength > inresultSize)
617 (void*)((unsigned long)queryComplete + queryComplete->InformationBufferOffset),
618 queryComplete->InformationBufferLength);
620 *ResultSize = queryComplete->InformationBufferLength;
625 PutRndisRequest(Device, request);
633 RndisFilterQueryDeviceMac(
637 u32 size=HW_MACADDR_LEN;
639 return RndisFilterQueryDevice(Device,
640 RNDIS_OID_802_3_PERMANENT_ADDRESS,
646 RndisFilterQueryDeviceLinkStatus(
650 u32 size=sizeof(u32);
652 return RndisFilterQueryDevice(Device,
653 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
659 RndisFilterSetPacketFilter(
660 RNDIS_DEVICE *Device,
664 RNDIS_REQUEST *request;
665 struct rndis_set_request *set;
666 struct rndis_set_complete *setComplete;
670 DPRINT_ENTER(NETVSC);
672 ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= sizeof(struct rndis_message));
674 request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32));
681 /* Setup the rndis set */
682 set = &request->RequestMessage.Message.SetRequest;
683 set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
684 set->InformationBufferLength = sizeof(u32);
685 set->InformationBufferOffset = sizeof(struct rndis_set_request);
687 memcpy((void*)(unsigned long)set + sizeof(struct rndis_set_request), &NewFilter, sizeof(u32));
689 ret = RndisFilterSendRequest(Device, request);
695 ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
699 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
700 /* We cant deallocate the request since we may still receive a send completion for it. */
709 setComplete = &request->ResponseMessage.Message.SetComplete;
710 status = setComplete->Status;
716 PutRndisRequest(Device, request);
724 int RndisFilterInit(struct netvsc_driver *Driver)
726 DPRINT_ENTER(NETVSC);
728 DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %zd", sizeof(RNDIS_FILTER_PACKET));
730 Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
731 Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
733 /* Driver->Context = rndisDriver; */
735 memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
737 /*rndisDriver->Driver = Driver;
739 ASSERT(Driver->OnLinkStatusChanged);
740 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
742 /* Save the original dispatch handlers before we override it */
743 gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
744 gRndisFilter.InnerDriver.Base.OnDeviceRemove = Driver->Base.OnDeviceRemove;
745 gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
747 ASSERT(Driver->OnSend);
748 ASSERT(Driver->OnReceiveCallback);
749 gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
750 gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
751 gRndisFilter.InnerDriver.OnLinkStatusChanged = Driver->OnLinkStatusChanged;
754 Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
755 Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
756 Driver->Base.OnCleanup = RndisFilterOnCleanup;
757 Driver->OnSend = RndisFilterOnSend;
758 Driver->OnOpen = RndisFilterOnOpen;
759 Driver->OnClose = RndisFilterOnClose;
760 /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
761 Driver->OnReceiveCallback = RndisFilterOnReceive;
769 RndisFilterInitDevice(
773 RNDIS_REQUEST *request;
774 struct rndis_initialize_request *init;
775 struct rndis_initialize_complete *initComplete;
779 DPRINT_ENTER(NETVSC);
781 request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
788 /* Setup the rndis set */
789 init = &request->RequestMessage.Message.InitializeRequest;
790 init->MajorVersion = RNDIS_MAJOR_VERSION;
791 init->MinorVersion = RNDIS_MINOR_VERSION;
792 init->MaxTransferSize = 2048; /* FIXME: Use 1536 - rounded ethernet frame size */
794 Device->State = RNDIS_DEV_INITIALIZING;
796 ret = RndisFilterSendRequest(Device, request);
799 Device->State = RNDIS_DEV_UNINITIALIZED;
803 osd_WaitEventWait(request->WaitEvent);
805 initComplete = &request->ResponseMessage.Message.InitializeComplete;
806 status = initComplete->Status;
807 if (status == RNDIS_STATUS_SUCCESS)
809 Device->State = RNDIS_DEV_INITIALIZED;
814 Device->State = RNDIS_DEV_UNINITIALIZED;
821 PutRndisRequest(Device, request);
829 RndisFilterHaltDevice(
833 RNDIS_REQUEST *request;
834 struct rndis_halt_request *halt;
836 DPRINT_ENTER(NETVSC);
838 /* Attempt to do a rndis device halt */
839 request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
845 /* Setup the rndis set */
846 halt = &request->RequestMessage.Message.HaltRequest;
847 halt->RequestId = atomic_inc_return(&Device->NewRequestId);
849 /* Ignore return since this msg is optional. */
850 RndisFilterSendRequest(Device, request);
852 Device->State = RNDIS_DEV_UNINITIALIZED;
857 PutRndisRequest(Device, request);
865 RndisFilterOpenDevice(
871 DPRINT_ENTER(NETVSC);
873 if (Device->State != RNDIS_DEV_INITIALIZED)
876 ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
879 Device->State = RNDIS_DEV_DATAINITIALIZED;
887 RndisFilterCloseDevice(
893 DPRINT_ENTER(NETVSC);
895 if (Device->State != RNDIS_DEV_DATAINITIALIZED)
898 ret = RndisFilterSetPacketFilter(Device, 0);
901 Device->State = RNDIS_DEV_INITIALIZED;
911 RndisFilterOnDeviceAdd(
912 struct hv_device *Device,
917 struct NETVSC_DEVICE *netDevice;
918 RNDIS_DEVICE *rndisDevice;
919 struct netvsc_device_info *deviceInfo = (struct netvsc_device_info *)AdditionalInfo;
921 DPRINT_ENTER(NETVSC);
923 rndisDevice = GetRndisDevice();
930 DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
932 /* Let the inner driver handle this first to create the netvsc channel */
933 /* NOTE! Once the channel is created, we may get a receive callback */
934 /* (RndisFilterOnReceive()) before this call is completed */
935 ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
938 PutRndisDevice(rndisDevice);
944 /* Initialize the rndis device */
946 netDevice = (struct NETVSC_DEVICE*)Device->Extension;
948 ASSERT(netDevice->Device);
950 netDevice->Extension = rndisDevice;
951 rndisDevice->NetDevice = netDevice;
953 /* Send the rndis initialization message */
954 ret = RndisFilterInitDevice(rndisDevice);
957 /* TODO: If rndis init failed, we will need to shut down the channel */
960 /* Get the mac address */
961 ret = RndisFilterQueryDeviceMac(rndisDevice);
964 /* TODO: shutdown rndis device and the channel */
967 DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
969 rndisDevice->HwMacAddr[0],
970 rndisDevice->HwMacAddr[1],
971 rndisDevice->HwMacAddr[2],
972 rndisDevice->HwMacAddr[3],
973 rndisDevice->HwMacAddr[4],
974 rndisDevice->HwMacAddr[5]);
976 memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
978 RndisFilterQueryDeviceLinkStatus(rndisDevice);
980 deviceInfo->LinkState = rndisDevice->LinkStatus;
981 DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, ((deviceInfo->LinkState)?("down"):("up")));
990 RndisFilterOnDeviceRemove(
991 struct hv_device *Device
994 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
995 RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
997 DPRINT_ENTER(NETVSC);
999 /* Halt and release the rndis device */
1000 RndisFilterHaltDevice(rndisDevice);
1002 PutRndisDevice(rndisDevice);
1003 netDevice->Extension = NULL;
1005 /* Pass control to inner driver to remove the device */
1006 gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
1008 DPRINT_EXIT(NETVSC);
1015 RndisFilterOnCleanup(
1016 struct hv_driver *Driver
1019 DPRINT_ENTER(NETVSC);
1021 DPRINT_EXIT(NETVSC);
1026 struct hv_device *Device
1030 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
1032 DPRINT_ENTER(NETVSC);
1035 ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
1037 DPRINT_EXIT(NETVSC);
1044 struct hv_device *Device
1048 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
1050 DPRINT_ENTER(NETVSC);
1053 ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
1055 DPRINT_EXIT(NETVSC);
1063 struct hv_device *Device,
1064 struct hv_netvsc_packet *Packet
1068 RNDIS_FILTER_PACKET *filterPacket;
1069 struct rndis_message *rndisMessage;
1070 struct rndis_packet *rndisPacket;
1071 u32 rndisMessageSize;
1073 DPRINT_ENTER(NETVSC);
1075 /* Add the rndis header */
1076 filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
1077 ASSERT(filterPacket);
1079 memset(filterPacket, 0, sizeof(RNDIS_FILTER_PACKET));
1081 rndisMessage = &filterPacket->Message;
1082 rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
1084 rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
1085 rndisMessage->MessageLength = Packet->TotalDataBufferLength + rndisMessageSize;
1087 rndisPacket = &rndisMessage->Message.Packet;
1088 rndisPacket->DataOffset = sizeof(struct rndis_packet);
1089 rndisPacket->DataLength = Packet->TotalDataBufferLength;
1091 Packet->IsDataPacket = true;
1092 Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
1093 Packet->PageBuffers[0].Offset = (unsigned long)rndisMessage & (PAGE_SIZE-1);
1094 Packet->PageBuffers[0].Length = rndisMessageSize;
1096 /* Save the packet send completion and context */
1097 filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
1098 filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
1101 Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
1102 Packet->Completion.Send.SendCompletionContext = filterPacket;
1104 ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
1107 /* Reset the completion to originals to allow retries from above */
1108 Packet->Completion.Send.OnSendCompletion = filterPacket->OnCompletion;
1109 Packet->Completion.Send.SendCompletionContext = filterPacket->CompletionContext;
1112 DPRINT_EXIT(NETVSC);
1118 RndisFilterOnSendCompletion(
1121 RNDIS_FILTER_PACKET *filterPacket = (RNDIS_FILTER_PACKET *)Context;
1123 DPRINT_ENTER(NETVSC);
1125 /* Pass it back to the original handler */
1126 filterPacket->OnCompletion(filterPacket->CompletionContext);
1128 DPRINT_EXIT(NETVSC);
1133 RndisFilterOnSendRequestCompletion(
1137 DPRINT_ENTER(NETVSC);
1140 DPRINT_EXIT(NETVSC);