Staging: hv: osd: remove physical address wrapper functions
[linux-2.6/mini2440.git] / drivers / staging / hv / RndisFilter.c
blob70dd17511b88daf2bbe428d797e14715f222f597
1 /*
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
12 * more details.
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.
18 * Authors:
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>
27 #include <asm/io.h>
29 #include "include/logging.h"
31 #include "include/NetVscApi.h"
32 #include "RndisFilter.h"
35 /* Data types */
38 typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
39 /* The original driver */
40 NETVSC_DRIVER_OBJECT InnerDriver;
42 } RNDIS_FILTER_DRIVER_OBJECT;
44 typedef enum {
45 RNDIS_DEV_UNINITIALIZED = 0,
46 RNDIS_DEV_INITIALIZING,
47 RNDIS_DEV_INITIALIZED,
48 RNDIS_DEV_DATAINITIALIZED,
49 } RNDIS_DEVICE_STATE;
51 typedef struct _RNDIS_DEVICE {
52 struct NETVSC_DEVICE *NetDevice;
54 RNDIS_DEVICE_STATE State;
55 u32 LinkStatus;
56 atomic_t NewRequestId;
58 spinlock_t request_lock;
59 LIST_ENTRY RequestList;
61 unsigned char HwMacAddr[HW_MACADDR_LEN];
62 } RNDIS_DEVICE;
65 typedef struct _RNDIS_REQUEST {
66 LIST_ENTRY ListEntry;
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;
75 PAGE_BUFFER Buffer;
76 /* FIXME: We assumed a fixed size request here. */
77 RNDIS_MESSAGE RequestMessage;
78 } RNDIS_REQUEST;
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 */
91 static int
92 RndisFilterSendRequest(
93 RNDIS_DEVICE *Device,
94 RNDIS_REQUEST *Request
97 static void
98 RndisFilterReceiveResponse(
99 RNDIS_DEVICE *Device,
100 RNDIS_MESSAGE *Response
103 static void
104 RndisFilterReceiveIndicateStatus(
105 RNDIS_DEVICE *Device,
106 RNDIS_MESSAGE *Response
109 static void
110 RndisFilterReceiveData(
111 RNDIS_DEVICE *Device,
112 RNDIS_MESSAGE *Message,
113 struct hv_netvsc_packet *Packet
116 static int
117 RndisFilterOnReceive(
118 struct hv_device *Device,
119 struct hv_netvsc_packet *Packet
122 static int
123 RndisFilterQueryDevice(
124 RNDIS_DEVICE *Device,
125 u32 Oid,
126 void *Result,
127 u32 *ResultSize
130 static inline int
131 RndisFilterQueryDeviceMac(
132 RNDIS_DEVICE *Device
135 static inline int
136 RndisFilterQueryDeviceLinkStatus(
137 RNDIS_DEVICE *Device
140 static int
141 RndisFilterSetPacketFilter(
142 RNDIS_DEVICE *Device,
143 u32 NewFilter
146 static int
147 RndisFilterInitDevice(
148 RNDIS_DEVICE *Device
151 static int
152 RndisFilterOpenDevice(
153 RNDIS_DEVICE *Device
156 static int
157 RndisFilterCloseDevice(
158 RNDIS_DEVICE *Device
161 static int
162 RndisFilterOnDeviceAdd(
163 struct hv_device *Device,
164 void *AdditionalInfo
167 static int
168 RndisFilterOnDeviceRemove(
169 struct hv_device *Device
172 static void
173 RndisFilterOnCleanup(
174 struct hv_driver *Driver
177 static int
178 RndisFilterOnOpen(
179 struct hv_device *Device
182 static int
183 RndisFilterOnClose(
184 struct hv_device *Device
187 static int
188 RndisFilterOnSend(
189 struct hv_device *Device,
190 struct hv_netvsc_packet *Packet
193 static void
194 RndisFilterOnSendCompletion(
195 void *Context
198 static void
199 RndisFilterOnSendRequestCompletion(
200 void *Context
204 /* Global var */
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);
215 if (!device)
217 return NULL;
220 spin_lock_init(&device->request_lock);
222 INITIALIZE_LIST_HEAD(&device->RequestList);
224 device->State = RNDIS_DEV_UNINITIALIZED;
226 return device;
229 static inline void PutRndisDevice(RNDIS_DEVICE *Device)
231 kfree(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;
239 unsigned long flags;
241 request = kzalloc(sizeof(RNDIS_REQUEST), GFP_KERNEL);
242 if (!request)
244 return NULL;
247 request->WaitEvent = WaitEventCreate();
248 if (!request->WaitEvent)
250 kfree(request);
251 return NULL;
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);
268 return request;
271 static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
273 unsigned long flags;
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);
280 kfree(Request);
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);
297 break;
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);
310 break;
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);
319 break;
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);
326 break;
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);
334 break;
336 default:
337 DPRINT_DBG(NETVSC, "0x%x (len %u)",
338 RndisMessage->NdisMessageType,
339 RndisMessage->MessageLength);
340 break;
344 static int
345 RndisFilterSendRequest(
346 RNDIS_DEVICE *Device,
347 RNDIS_REQUEST *Request
350 int ret=0;
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);
371 DPRINT_EXIT(NETVSC);
372 return ret;
376 static void
377 RndisFilterReceiveResponse(
378 RNDIS_DEVICE *Device,
379 RNDIS_MESSAGE *Response
382 LIST_ENTRY *anchor;
383 LIST_ENTRY *curr;
384 RNDIS_REQUEST *request=NULL;
385 bool found = false;
386 unsigned long flags;
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);
401 found = true;
402 break;
405 spin_unlock_irqrestore(&Device->request_lock, flags);
407 if (found)
409 if (Response->MessageLength <= sizeof(RNDIS_MESSAGE))
411 memcpy(&request->ResponseMessage, Response, Response->MessageLength);
413 else
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;
421 else
423 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
427 WaitEventSet(request->WaitEvent);
429 else
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);
435 DPRINT_EXIT(NETVSC);
438 static void
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);
454 else
456 /* TODO: */
460 static void
461 RndisFilterReceiveData(
462 RNDIS_DEVICE *Device,
463 RNDIS_MESSAGE *Message,
464 struct hv_netvsc_packet *Packet
467 RNDIS_PACKET *rndisPacket;
468 u32 dataOffset;
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);
491 DPRINT_EXIT(NETVSC);
494 static int
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);
507 ASSERT(netDevice);
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!");
512 DPRINT_EXIT(NETVSC);
513 return -1;
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!");
520 DPRINT_EXIT(NETVSC);
521 return -1;
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 */
531 #if 0
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);
538 DPRINT_EXIT(NETVSC);
539 return -1;
541 #endif
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)
557 /* data msg */
558 case REMOTE_NDIS_PACKET_MSG:
559 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
560 break;
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);
569 break;
571 /* notification msgs */
572 case REMOTE_NDIS_INDICATE_STATUS_MSG:
573 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
574 break;
575 default:
576 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", rndisMessage.NdisMessageType, rndisMessage.MessageLength);
577 break;
580 DPRINT_EXIT(NETVSC);
581 return 0;
585 static int
586 RndisFilterQueryDevice(
587 RNDIS_DEVICE *Device,
588 u32 Oid,
589 void *Result,
590 u32 *ResultSize
593 RNDIS_REQUEST *request;
594 u32 inresultSize = *ResultSize;
595 RNDIS_QUERY_REQUEST *query;
596 RNDIS_QUERY_COMPLETE *queryComplete;
597 int ret=0;
599 DPRINT_ENTER(NETVSC);
601 ASSERT(Result);
603 *ResultSize = 0;
604 request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST));
605 if (!request)
607 ret = -1;
608 goto Cleanup;
611 /* Setup the rndis query */
612 query = &request->RequestMessage.Message.QueryRequest;
613 query->Oid = Oid;
614 query->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
615 query->InformationBufferLength = 0;
616 query->DeviceVcHandle = 0;
618 ret = RndisFilterSendRequest(Device, request);
619 if (ret != 0)
621 goto Cleanup;
624 WaitEventWait(request->WaitEvent);
626 /* Copy the response back */
627 queryComplete = &request->ResponseMessage.Message.QueryComplete;
629 if (queryComplete->InformationBufferLength > inresultSize)
631 ret = -1;
632 goto Cleanup;
635 memcpy(Result,
636 (void*)((unsigned long)queryComplete + queryComplete->InformationBufferOffset),
637 queryComplete->InformationBufferLength);
639 *ResultSize = queryComplete->InformationBufferLength;
641 Cleanup:
642 if (request)
644 PutRndisRequest(Device, request);
646 DPRINT_EXIT(NETVSC);
648 return ret;
651 static inline int
652 RndisFilterQueryDeviceMac(
653 RNDIS_DEVICE *Device
656 u32 size=HW_MACADDR_LEN;
658 return RndisFilterQueryDevice(Device,
659 RNDIS_OID_802_3_PERMANENT_ADDRESS,
660 Device->HwMacAddr,
661 &size);
664 static inline int
665 RndisFilterQueryDeviceLinkStatus(
666 RNDIS_DEVICE *Device
669 u32 size=sizeof(u32);
671 return RndisFilterQueryDevice(Device,
672 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
673 &Device->LinkStatus,
674 &size);
677 static int
678 RndisFilterSetPacketFilter(
679 RNDIS_DEVICE *Device,
680 u32 NewFilter
683 RNDIS_REQUEST *request;
684 RNDIS_SET_REQUEST *set;
685 RNDIS_SET_COMPLETE *setComplete;
686 u32 status;
687 int ret;
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));
694 if (!request)
696 ret = -1;
697 goto Cleanup;
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);
709 if (ret != 0)
711 goto Cleanup;
714 ret = WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
715 if (!ret)
717 ret = -1;
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. */
720 goto Exit;
722 else
724 if (ret > 0)
726 ret = 0;
728 setComplete = &request->ResponseMessage.Message.SetComplete;
729 status = setComplete->Status;
732 Cleanup:
733 if (request)
735 PutRndisRequest(Device, request);
737 Exit:
738 DPRINT_EXIT(NETVSC);
740 return ret;
744 RndisFilterInit(
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;
775 /* Override */
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;
785 DPRINT_EXIT(NETVSC);
787 return 0;
790 static int
791 RndisFilterInitDevice(
792 RNDIS_DEVICE *Device
795 RNDIS_REQUEST *request;
796 RNDIS_INITIALIZE_REQUEST *init;
797 RNDIS_INITIALIZE_COMPLETE *initComplete;
798 u32 status;
799 int ret;
801 DPRINT_ENTER(NETVSC);
803 request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST));
804 if (!request)
806 ret = -1;
807 goto Cleanup;
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);
819 if (ret != 0)
821 Device->State = RNDIS_DEV_UNINITIALIZED;
822 goto Cleanup;
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;
832 ret = 0;
834 else
836 Device->State = RNDIS_DEV_UNINITIALIZED;
837 ret = -1;
840 Cleanup:
841 if (request)
843 PutRndisRequest(Device, request);
845 DPRINT_EXIT(NETVSC);
847 return ret;
850 static void
851 RndisFilterHaltDevice(
852 RNDIS_DEVICE *Device
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));
862 if (!request)
864 goto Cleanup;
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;
876 Cleanup:
877 if (request)
879 PutRndisRequest(Device, request);
881 DPRINT_EXIT(NETVSC);
882 return;
886 static int
887 RndisFilterOpenDevice(
888 RNDIS_DEVICE *Device
891 int ret=0;
893 DPRINT_ENTER(NETVSC);
895 if (Device->State != RNDIS_DEV_INITIALIZED)
896 return 0;
898 ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
899 if (ret == 0)
901 Device->State = RNDIS_DEV_DATAINITIALIZED;
904 DPRINT_EXIT(NETVSC);
905 return ret;
908 static int
909 RndisFilterCloseDevice(
910 RNDIS_DEVICE *Device
913 int ret;
915 DPRINT_ENTER(NETVSC);
917 if (Device->State != RNDIS_DEV_DATAINITIALIZED)
918 return 0;
920 ret = RndisFilterSetPacketFilter(Device, 0);
921 if (ret == 0)
923 Device->State = RNDIS_DEV_INITIALIZED;
926 DPRINT_EXIT(NETVSC);
928 return ret;
932 static int
933 RndisFilterOnDeviceAdd(
934 struct hv_device *Device,
935 void *AdditionalInfo
938 int ret;
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();
946 if (!rndisDevice)
948 DPRINT_EXIT(NETVSC);
949 return -1;
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);
958 if (ret != 0)
960 PutRndisDevice(rndisDevice);
961 DPRINT_EXIT(NETVSC);
962 return ret;
966 /* Initialize the rndis device */
968 netDevice = (struct NETVSC_DEVICE*)Device->Extension;
969 ASSERT(netDevice);
970 ASSERT(netDevice->Device);
972 netDevice->Extension = rndisDevice;
973 rndisDevice->NetDevice = netDevice;
975 /* Send the rndis initialization message */
976 ret = RndisFilterInitDevice(rndisDevice);
977 if (ret != 0)
979 /* TODO: If rndis init failed, we will need to shut down the channel */
982 /* Get the mac address */
983 ret = RndisFilterQueryDeviceMac(rndisDevice);
984 if (ret != 0)
986 /* TODO: shutdown rndis device and the channel */
989 DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
990 rndisDevice,
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);
1007 return ret;
1011 static int
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);
1032 return 0;
1036 static void
1037 RndisFilterOnCleanup(
1038 struct hv_driver *Driver
1041 DPRINT_ENTER(NETVSC);
1043 DPRINT_EXIT(NETVSC);
1046 static int
1047 RndisFilterOnOpen(
1048 struct hv_device *Device
1051 int ret;
1052 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
1054 DPRINT_ENTER(NETVSC);
1056 ASSERT(netDevice);
1057 ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
1059 DPRINT_EXIT(NETVSC);
1061 return ret;
1064 static int
1065 RndisFilterOnClose(
1066 struct hv_device *Device
1069 int ret;
1070 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
1072 DPRINT_ENTER(NETVSC);
1074 ASSERT(netDevice);
1075 ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
1077 DPRINT_EXIT(NETVSC);
1079 return ret;
1083 static int
1084 RndisFilterOnSend(
1085 struct hv_device *Device,
1086 struct hv_netvsc_packet *Packet
1089 int ret=0;
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;
1122 /* Use ours */
1123 Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
1124 Packet->Completion.Send.SendCompletionContext = filterPacket;
1126 ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
1127 if (ret != 0)
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);
1136 return ret;
1139 static void
1140 RndisFilterOnSendCompletion(
1141 void *Context)
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);
1154 static void
1155 RndisFilterOnSendRequestCompletion(
1156 void *Context
1159 DPRINT_ENTER(NETVSC);
1161 /* Noop */
1162 DPRINT_EXIT(NETVSC);