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>
26 #include "NetVscApi.h"
27 #include "RndisFilter.h"
30 struct rndis_filter_driver_object {
31 /* The original driver */
32 struct netvsc_driver InnerDriver;
35 enum rndis_device_state {
36 RNDIS_DEV_UNINITIALIZED = 0,
37 RNDIS_DEV_INITIALIZING,
38 RNDIS_DEV_INITIALIZED,
39 RNDIS_DEV_DATAINITIALIZED,
43 struct netvsc_device *NetDevice;
45 enum rndis_device_state State;
47 atomic_t NewRequestId;
49 spinlock_t request_lock;
50 struct list_head RequestList;
52 unsigned char HwMacAddr[HW_MACADDR_LEN];
55 struct rndis_request {
56 struct list_head ListEntry;
57 struct osd_waitevent *WaitEvent;
60 * FIXME: We assumed a fixed size response here. If we do ever need to
61 * handle a bigger response, we can either define a max response
62 * message or add a response buffer variable above this field
64 struct rndis_message ResponseMessage;
66 /* Simplify allocation by having a netvsc packet inline */
67 struct hv_netvsc_packet Packet;
68 struct hv_page_buffer Buffer;
69 /* FIXME: We assumed a fixed size request here. */
70 struct rndis_message RequestMessage;
74 struct rndis_filter_packet {
75 void *CompletionContext;
76 void (*OnCompletion)(void *context);
77 struct rndis_message Message;
81 static int RndisFilterOnDeviceAdd(struct hv_device *Device,
82 void *AdditionalInfo);
84 static int RndisFilterOnDeviceRemove(struct hv_device *Device);
86 static void RndisFilterOnCleanup(struct hv_driver *Driver);
88 static int RndisFilterOnSend(struct hv_device *Device,
89 struct hv_netvsc_packet *Packet);
91 static void RndisFilterOnSendCompletion(void *Context);
93 static void RndisFilterOnSendRequestCompletion(void *Context);
96 /* The one and only */
97 static struct rndis_filter_driver_object gRndisFilter;
99 static struct rndis_device *GetRndisDevice(void)
101 struct rndis_device *device;
103 device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
107 spin_lock_init(&device->request_lock);
109 INIT_LIST_HEAD(&device->RequestList);
111 device->State = RNDIS_DEV_UNINITIALIZED;
116 static struct rndis_request *GetRndisRequest(struct rndis_device *Device,
120 struct rndis_request *request;
121 struct rndis_message *rndisMessage;
122 struct rndis_set_request *set;
125 request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
129 request->WaitEvent = osd_WaitEventCreate();
130 if (!request->WaitEvent) {
135 rndisMessage = &request->RequestMessage;
136 rndisMessage->NdisMessageType = MessageType;
137 rndisMessage->MessageLength = MessageLength;
140 * Set the request id. This field is always after the rndis header for
141 * request/response packet types so we just used the SetRequest as a
144 set = &rndisMessage->Message.SetRequest;
145 set->RequestId = atomic_inc_return(&Device->NewRequestId);
147 /* Add to the request list */
148 spin_lock_irqsave(&Device->request_lock, flags);
149 list_add_tail(&request->ListEntry, &Device->RequestList);
150 spin_unlock_irqrestore(&Device->request_lock, flags);
155 static void PutRndisRequest(struct rndis_device *Device,
156 struct rndis_request *Request)
160 spin_lock_irqsave(&Device->request_lock, flags);
161 list_del(&Request->ListEntry);
162 spin_unlock_irqrestore(&Device->request_lock, flags);
164 kfree(Request->WaitEvent);
168 static void DumpRndisMessage(struct rndis_message *RndisMessage)
170 switch (RndisMessage->NdisMessageType) {
171 case REMOTE_NDIS_PACKET_MSG:
172 DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
173 "data offset %u data len %u, # oob %u, "
174 "oob offset %u, oob len %u, pkt offset %u, "
176 RndisMessage->MessageLength,
177 RndisMessage->Message.Packet.DataOffset,
178 RndisMessage->Message.Packet.DataLength,
179 RndisMessage->Message.Packet.NumOOBDataElements,
180 RndisMessage->Message.Packet.OOBDataOffset,
181 RndisMessage->Message.Packet.OOBDataLength,
182 RndisMessage->Message.Packet.PerPacketInfoOffset,
183 RndisMessage->Message.Packet.PerPacketInfoLength);
186 case REMOTE_NDIS_INITIALIZE_CMPLT:
187 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
188 "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
189 "device flags %d, max xfer size 0x%x, max pkts %u, "
191 RndisMessage->MessageLength,
192 RndisMessage->Message.InitializeComplete.RequestId,
193 RndisMessage->Message.InitializeComplete.Status,
194 RndisMessage->Message.InitializeComplete.MajorVersion,
195 RndisMessage->Message.InitializeComplete.MinorVersion,
196 RndisMessage->Message.InitializeComplete.DeviceFlags,
197 RndisMessage->Message.InitializeComplete.MaxTransferSize,
198 RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
199 RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
202 case REMOTE_NDIS_QUERY_CMPLT:
203 DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
204 "(len %u, id 0x%x, status 0x%x, buf len %u, "
206 RndisMessage->MessageLength,
207 RndisMessage->Message.QueryComplete.RequestId,
208 RndisMessage->Message.QueryComplete.Status,
209 RndisMessage->Message.QueryComplete.InformationBufferLength,
210 RndisMessage->Message.QueryComplete.InformationBufferOffset);
213 case REMOTE_NDIS_SET_CMPLT:
215 "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
216 RndisMessage->MessageLength,
217 RndisMessage->Message.SetComplete.RequestId,
218 RndisMessage->Message.SetComplete.Status);
221 case REMOTE_NDIS_INDICATE_STATUS_MSG:
222 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
223 "(len %u, status 0x%x, buf len %u, buf offset %u)",
224 RndisMessage->MessageLength,
225 RndisMessage->Message.IndicateStatus.Status,
226 RndisMessage->Message.IndicateStatus.StatusBufferLength,
227 RndisMessage->Message.IndicateStatus.StatusBufferOffset);
231 DPRINT_DBG(NETVSC, "0x%x (len %u)",
232 RndisMessage->NdisMessageType,
233 RndisMessage->MessageLength);
238 static int RndisFilterSendRequest(struct rndis_device *Device,
239 struct rndis_request *Request)
242 struct hv_netvsc_packet *packet;
244 DPRINT_ENTER(NETVSC);
246 /* Setup the packet to send it */
247 packet = &Request->Packet;
249 packet->IsDataPacket = false;
250 packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
251 packet->PageBufferCount = 1;
253 packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >>
255 packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
256 packet->PageBuffers[0].Offset =
257 (unsigned long)&Request->RequestMessage & (PAGE_SIZE - 1);
259 packet->Completion.Send.SendCompletionContext = Request;/* packet; */
260 packet->Completion.Send.OnSendCompletion =
261 RndisFilterOnSendRequestCompletion;
262 packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
264 ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
269 static void RndisFilterReceiveResponse(struct rndis_device *Device,
270 struct rndis_message *Response)
272 struct rndis_request *request = NULL;
276 DPRINT_ENTER(NETVSC);
278 spin_lock_irqsave(&Device->request_lock, flags);
279 list_for_each_entry(request, &Device->RequestList, ListEntry) {
281 * All request/response message contains RequestId as the 1st
284 if (request->RequestMessage.Message.InitializeRequest.RequestId
285 == Response->Message.InitializeComplete.RequestId) {
286 DPRINT_DBG(NETVSC, "found rndis request for "
287 "this response (id 0x%x req type 0x%x res "
289 request->RequestMessage.Message.InitializeRequest.RequestId,
290 request->RequestMessage.NdisMessageType,
291 Response->NdisMessageType);
297 spin_unlock_irqrestore(&Device->request_lock, flags);
300 if (Response->MessageLength <= sizeof(struct rndis_message)) {
301 memcpy(&request->ResponseMessage, Response,
302 Response->MessageLength);
304 DPRINT_ERR(NETVSC, "rndis response buffer overflow "
305 "detected (size %u max %zu)",
306 Response->MessageLength,
307 sizeof(struct rndis_filter_packet));
309 if (Response->NdisMessageType ==
310 REMOTE_NDIS_RESET_CMPLT) {
311 /* does not have a request id field */
312 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
314 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
318 osd_WaitEventSet(request->WaitEvent);
320 DPRINT_ERR(NETVSC, "no rndis request found for this response "
321 "(id 0x%x res type 0x%x)",
322 Response->Message.InitializeComplete.RequestId,
323 Response->NdisMessageType);
329 static void RndisFilterReceiveIndicateStatus(struct rndis_device *Device,
330 struct rndis_message *Response)
332 struct rndis_indicate_status *indicate =
333 &Response->Message.IndicateStatus;
335 if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT) {
336 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
337 } else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT) {
338 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
346 static void RndisFilterReceiveData(struct rndis_device *Device,
347 struct rndis_message *Message,
348 struct hv_netvsc_packet *Packet)
350 struct rndis_packet *rndisPacket;
353 DPRINT_ENTER(NETVSC);
355 /* empty ethernet frame ?? */
356 ASSERT(Packet->PageBuffers[0].Length >
357 RNDIS_MESSAGE_SIZE(struct rndis_packet));
359 rndisPacket = &Message->Message.Packet;
362 * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
363 * netvsc packet (ie TotalDataBufferLength != MessageLength)
366 /* Remove the rndis header and pass it back up the stack */
367 dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
369 Packet->TotalDataBufferLength -= dataOffset;
370 Packet->PageBuffers[0].Offset += dataOffset;
371 Packet->PageBuffers[0].Length -= dataOffset;
373 Packet->IsDataPacket = true;
375 gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device,
381 static int RndisFilterOnReceive(struct hv_device *Device,
382 struct hv_netvsc_packet *Packet)
384 struct netvsc_device *netDevice = Device->Extension;
385 struct rndis_device *rndisDevice;
386 struct rndis_message rndisMessage;
387 struct rndis_message *rndisHeader;
389 DPRINT_ENTER(NETVSC);
392 /* Make sure the rndis device state is initialized */
393 if (!netDevice->Extension) {
394 DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
395 "dropping this message!");
400 rndisDevice = (struct rndis_device *)netDevice->Extension;
401 if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED) {
402 DPRINT_ERR(NETVSC, "got rndis message but rndis device "
403 "uninitialized...dropping this message!");
408 rndisHeader = (struct rndis_message *)kmap_atomic(
409 pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
411 rndisHeader = (void *)((unsigned long)rndisHeader +
412 Packet->PageBuffers[0].Offset);
414 /* Make sure we got a valid rndis message */
416 * FIXME: There seems to be a bug in set completion msg where its
417 * MessageLength is 16 bytes but the ByteCount field in the xfer page
418 * range shows 52 bytes
421 if (Packet->TotalDataBufferLength != rndisHeader->MessageLength) {
422 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset,
425 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
426 "bytes got %u)...dropping this message!",
427 rndisHeader->MessageLength,
428 Packet->TotalDataBufferLength);
434 if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) &&
435 (rndisHeader->MessageLength > sizeof(struct rndis_message))) {
436 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow "
437 "detected (got %u, max %zu)...marking it an error!",
438 rndisHeader->MessageLength,
439 sizeof(struct rndis_message));
442 memcpy(&rndisMessage, rndisHeader,
443 (rndisHeader->MessageLength > sizeof(struct rndis_message)) ?
444 sizeof(struct rndis_message) :
445 rndisHeader->MessageLength);
447 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
449 DumpRndisMessage(&rndisMessage);
451 switch (rndisMessage.NdisMessageType) {
452 case REMOTE_NDIS_PACKET_MSG:
454 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
457 case REMOTE_NDIS_INITIALIZE_CMPLT:
458 case REMOTE_NDIS_QUERY_CMPLT:
459 case REMOTE_NDIS_SET_CMPLT:
460 /* case REMOTE_NDIS_RESET_CMPLT: */
461 /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
462 /* completion msgs */
463 RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
466 case REMOTE_NDIS_INDICATE_STATUS_MSG:
467 /* notification msgs */
468 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
471 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)",
472 rndisMessage.NdisMessageType,
473 rndisMessage.MessageLength);
481 static int RndisFilterQueryDevice(struct rndis_device *Device, u32 Oid,
482 void *Result, u32 *ResultSize)
484 struct rndis_request *request;
485 u32 inresultSize = *ResultSize;
486 struct rndis_query_request *query;
487 struct rndis_query_complete *queryComplete;
490 DPRINT_ENTER(NETVSC);
495 request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG,
496 RNDIS_MESSAGE_SIZE(struct rndis_query_request));
502 /* Setup the rndis query */
503 query = &request->RequestMessage.Message.QueryRequest;
505 query->InformationBufferOffset = sizeof(struct rndis_query_request);
506 query->InformationBufferLength = 0;
507 query->DeviceVcHandle = 0;
509 ret = RndisFilterSendRequest(Device, request);
513 osd_WaitEventWait(request->WaitEvent);
515 /* Copy the response back */
516 queryComplete = &request->ResponseMessage.Message.QueryComplete;
518 if (queryComplete->InformationBufferLength > inresultSize) {
524 (void *)((unsigned long)queryComplete +
525 queryComplete->InformationBufferOffset),
526 queryComplete->InformationBufferLength);
528 *ResultSize = queryComplete->InformationBufferLength;
532 PutRndisRequest(Device, request);
538 static int RndisFilterQueryDeviceMac(struct rndis_device *Device)
540 u32 size = HW_MACADDR_LEN;
542 return RndisFilterQueryDevice(Device,
543 RNDIS_OID_802_3_PERMANENT_ADDRESS,
544 Device->HwMacAddr, &size);
547 static int RndisFilterQueryDeviceLinkStatus(struct rndis_device *Device)
549 u32 size = sizeof(u32);
551 return RndisFilterQueryDevice(Device,
552 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
553 &Device->LinkStatus, &size);
556 static int RndisFilterSetPacketFilter(struct rndis_device *Device,
559 struct rndis_request *request;
560 struct rndis_set_request *set;
561 struct rndis_set_complete *setComplete;
565 DPRINT_ENTER(NETVSC);
567 ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <=
568 sizeof(struct rndis_message));
570 request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG,
571 RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
578 /* Setup the rndis set */
579 set = &request->RequestMessage.Message.SetRequest;
580 set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
581 set->InformationBufferLength = sizeof(u32);
582 set->InformationBufferOffset = sizeof(struct rndis_set_request);
584 memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
585 &NewFilter, sizeof(u32));
587 ret = RndisFilterSendRequest(Device, request);
591 ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
594 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
596 * We cant deallocate the request since we may still receive a
597 * send completion for it.
603 setComplete = &request->ResponseMessage.Message.SetComplete;
604 status = setComplete->Status;
609 PutRndisRequest(Device, request);
616 int RndisFilterInit(struct netvsc_driver *Driver)
618 DPRINT_ENTER(NETVSC);
620 DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd",
621 sizeof(struct rndis_filter_packet));
623 Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
624 Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
626 /* Driver->Context = rndisDriver; */
628 memset(&gRndisFilter, 0, sizeof(struct rndis_filter_driver_object));
630 /*rndisDriver->Driver = Driver;
632 ASSERT(Driver->OnLinkStatusChanged);
633 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
635 /* Save the original dispatch handlers before we override it */
636 gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
637 gRndisFilter.InnerDriver.Base.OnDeviceRemove =
638 Driver->Base.OnDeviceRemove;
639 gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
641 ASSERT(Driver->OnSend);
642 ASSERT(Driver->OnReceiveCallback);
643 gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
644 gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
645 gRndisFilter.InnerDriver.OnLinkStatusChanged =
646 Driver->OnLinkStatusChanged;
649 Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
650 Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
651 Driver->Base.OnCleanup = RndisFilterOnCleanup;
652 Driver->OnSend = RndisFilterOnSend;
653 /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
654 Driver->OnReceiveCallback = RndisFilterOnReceive;
661 static int RndisFilterInitDevice(struct rndis_device *Device)
663 struct rndis_request *request;
664 struct rndis_initialize_request *init;
665 struct rndis_initialize_complete *initComplete;
669 DPRINT_ENTER(NETVSC);
671 request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG,
672 RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
678 /* Setup the rndis set */
679 init = &request->RequestMessage.Message.InitializeRequest;
680 init->MajorVersion = RNDIS_MAJOR_VERSION;
681 init->MinorVersion = RNDIS_MINOR_VERSION;
682 /* FIXME: Use 1536 - rounded ethernet frame size */
683 init->MaxTransferSize = 2048;
685 Device->State = RNDIS_DEV_INITIALIZING;
687 ret = RndisFilterSendRequest(Device, request);
689 Device->State = RNDIS_DEV_UNINITIALIZED;
693 osd_WaitEventWait(request->WaitEvent);
695 initComplete = &request->ResponseMessage.Message.InitializeComplete;
696 status = initComplete->Status;
697 if (status == RNDIS_STATUS_SUCCESS) {
698 Device->State = RNDIS_DEV_INITIALIZED;
701 Device->State = RNDIS_DEV_UNINITIALIZED;
707 PutRndisRequest(Device, request);
713 static void RndisFilterHaltDevice(struct rndis_device *Device)
715 struct rndis_request *request;
716 struct rndis_halt_request *halt;
718 DPRINT_ENTER(NETVSC);
720 /* Attempt to do a rndis device halt */
721 request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG,
722 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
726 /* Setup the rndis set */
727 halt = &request->RequestMessage.Message.HaltRequest;
728 halt->RequestId = atomic_inc_return(&Device->NewRequestId);
730 /* Ignore return since this msg is optional. */
731 RndisFilterSendRequest(Device, request);
733 Device->State = RNDIS_DEV_UNINITIALIZED;
737 PutRndisRequest(Device, request);
742 static int RndisFilterOpenDevice(struct rndis_device *Device)
746 DPRINT_ENTER(NETVSC);
748 if (Device->State != RNDIS_DEV_INITIALIZED)
751 ret = RndisFilterSetPacketFilter(Device,
752 NDIS_PACKET_TYPE_BROADCAST |
753 NDIS_PACKET_TYPE_DIRECTED);
755 Device->State = RNDIS_DEV_DATAINITIALIZED;
761 static int RndisFilterCloseDevice(struct rndis_device *Device)
765 DPRINT_ENTER(NETVSC);
767 if (Device->State != RNDIS_DEV_DATAINITIALIZED)
770 ret = RndisFilterSetPacketFilter(Device, 0);
772 Device->State = RNDIS_DEV_INITIALIZED;
779 static int RndisFilterOnDeviceAdd(struct hv_device *Device,
780 void *AdditionalInfo)
783 struct netvsc_device *netDevice;
784 struct rndis_device *rndisDevice;
785 struct netvsc_device_info *deviceInfo = AdditionalInfo;
787 DPRINT_ENTER(NETVSC);
789 rndisDevice = GetRndisDevice();
795 DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
798 * Let the inner driver handle this first to create the netvsc channel
799 * NOTE! Once the channel is created, we may get a receive callback
800 * (RndisFilterOnReceive()) before this call is completed
802 ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
810 /* Initialize the rndis device */
811 netDevice = Device->Extension;
813 ASSERT(netDevice->Device);
815 netDevice->Extension = rndisDevice;
816 rndisDevice->NetDevice = netDevice;
818 /* Send the rndis initialization message */
819 ret = RndisFilterInitDevice(rndisDevice);
822 * TODO: If rndis init failed, we will need to shut down the
827 /* Get the mac address */
828 ret = RndisFilterQueryDeviceMac(rndisDevice);
831 * TODO: shutdown rndis device and the channel
835 DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
837 rndisDevice->HwMacAddr[0],
838 rndisDevice->HwMacAddr[1],
839 rndisDevice->HwMacAddr[2],
840 rndisDevice->HwMacAddr[3],
841 rndisDevice->HwMacAddr[4],
842 rndisDevice->HwMacAddr[5]);
844 memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
846 RndisFilterQueryDeviceLinkStatus(rndisDevice);
848 deviceInfo->LinkState = rndisDevice->LinkStatus;
849 DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice,
850 ((deviceInfo->LinkState) ? ("down") : ("up")));
857 static int RndisFilterOnDeviceRemove(struct hv_device *Device)
859 struct netvsc_device *netDevice = Device->Extension;
860 struct rndis_device *rndisDevice = netDevice->Extension;
862 DPRINT_ENTER(NETVSC);
864 /* Halt and release the rndis device */
865 RndisFilterHaltDevice(rndisDevice);
868 netDevice->Extension = NULL;
870 /* Pass control to inner driver to remove the device */
871 gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
878 static void RndisFilterOnCleanup(struct hv_driver *Driver)
880 DPRINT_ENTER(NETVSC);
885 int RndisFilterOnOpen(struct hv_device *Device)
888 struct netvsc_device *netDevice = Device->Extension;
890 DPRINT_ENTER(NETVSC);
893 ret = RndisFilterOpenDevice(netDevice->Extension);
900 int RndisFilterOnClose(struct hv_device *Device)
903 struct netvsc_device *netDevice = Device->Extension;
905 DPRINT_ENTER(NETVSC);
908 ret = RndisFilterCloseDevice(netDevice->Extension);
915 static int RndisFilterOnSend(struct hv_device *Device,
916 struct hv_netvsc_packet *Packet)
919 struct rndis_filter_packet *filterPacket;
920 struct rndis_message *rndisMessage;
921 struct rndis_packet *rndisPacket;
922 u32 rndisMessageSize;
924 DPRINT_ENTER(NETVSC);
926 /* Add the rndis header */
927 filterPacket = (struct rndis_filter_packet *)Packet->Extension;
928 ASSERT(filterPacket);
930 memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
932 rndisMessage = &filterPacket->Message;
933 rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
935 rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
936 rndisMessage->MessageLength = Packet->TotalDataBufferLength +
939 rndisPacket = &rndisMessage->Message.Packet;
940 rndisPacket->DataOffset = sizeof(struct rndis_packet);
941 rndisPacket->DataLength = Packet->TotalDataBufferLength;
943 Packet->IsDataPacket = true;
944 Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
945 Packet->PageBuffers[0].Offset =
946 (unsigned long)rndisMessage & (PAGE_SIZE-1);
947 Packet->PageBuffers[0].Length = rndisMessageSize;
949 /* Save the packet send completion and context */
950 filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
951 filterPacket->CompletionContext =
952 Packet->Completion.Send.SendCompletionContext;
955 Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
956 Packet->Completion.Send.SendCompletionContext = filterPacket;
958 ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
961 * Reset the completion to originals to allow retries from
964 Packet->Completion.Send.OnSendCompletion =
965 filterPacket->OnCompletion;
966 Packet->Completion.Send.SendCompletionContext =
967 filterPacket->CompletionContext;
975 static void RndisFilterOnSendCompletion(void *Context)
977 struct rndis_filter_packet *filterPacket = Context;
979 DPRINT_ENTER(NETVSC);
981 /* Pass it back to the original handler */
982 filterPacket->OnCompletion(filterPacket->CompletionContext);
988 static void RndisFilterOnSendRequestCompletion(void *Context)
990 DPRINT_ENTER(NETVSC);