blob: 5cd1575578a6c08850a5ebe66b05dcee7f49d5b7 [file] [log] [blame]
Hank Janssenfceaf242009-07-13 15:34:54 -07001/*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
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.
8 *
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.
13 *
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.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 *
22 */
23
Greg Kroah-Hartman5654e932009-07-14 15:08:20 -070024#include <linux/kernel.h>
Bill Pemberton45da89e2009-07-29 17:00:15 -040025#include <linux/highmem.h>
26#include <asm/kmap_types.h>
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -070027#include <asm/io.h>
Bill Pemberton45da89e2009-07-29 17:00:15 -040028
Greg Kroah-Hartmanc86f3e22009-07-14 10:59:56 -070029#include "include/logging.h"
Hank Janssenfceaf242009-07-13 15:34:54 -070030
Greg Kroah-Hartmanc86f3e22009-07-14 10:59:56 -070031#include "include/NetVscApi.h"
Hank Janssenfceaf242009-07-13 15:34:54 -070032#include "RndisFilter.h"
33
Bill Pemberton454f18a2009-07-27 16:47:24 -040034
35/* Data types */
36
Hank Janssenfceaf242009-07-13 15:34:54 -070037
38typedef struct _RNDIS_FILTER_DRIVER_OBJECT {
Bill Pemberton454f18a2009-07-27 16:47:24 -040039 /* The original driver */
Hank Janssenfceaf242009-07-13 15:34:54 -070040 NETVSC_DRIVER_OBJECT InnerDriver;
41
42} RNDIS_FILTER_DRIVER_OBJECT;
43
44typedef enum {
45 RNDIS_DEV_UNINITIALIZED = 0,
46 RNDIS_DEV_INITIALIZING,
47 RNDIS_DEV_INITIALIZED,
48 RNDIS_DEV_DATAINITIALIZED,
49} RNDIS_DEVICE_STATE;
50
51typedef struct _RNDIS_DEVICE {
Bill Pembertond1af1db72009-07-27 16:47:44 -040052 struct NETVSC_DEVICE *NetDevice;
Hank Janssenfceaf242009-07-13 15:34:54 -070053
54 RNDIS_DEVICE_STATE State;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070055 u32 LinkStatus;
Bill Pembertonf4888412009-07-29 17:00:12 -040056 atomic_t NewRequestId;
Hank Janssenfceaf242009-07-13 15:34:54 -070057
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -070058 spinlock_t request_lock;
Hank Janssenfceaf242009-07-13 15:34:54 -070059 LIST_ENTRY RequestList;
60
Greg Kroah-Hartman59471432009-07-14 15:10:26 -070061 unsigned char HwMacAddr[HW_MACADDR_LEN];
Hank Janssenfceaf242009-07-13 15:34:54 -070062} RNDIS_DEVICE;
63
64
65typedef struct _RNDIS_REQUEST {
66 LIST_ENTRY ListEntry;
Bill Pembertonaedb4442009-07-28 13:46:24 -040067 struct osd_waitevent *WaitEvent;
Hank Janssenfceaf242009-07-13 15:34:54 -070068
Bill Pemberton454f18a2009-07-27 16:47:24 -040069 /* 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 */
Hank Janssenfceaf242009-07-13 15:34:54 -070071 RNDIS_MESSAGE ResponseMessage;
72
Bill Pemberton454f18a2009-07-27 16:47:24 -040073 /* Simplify allocation by having a netvsc packet inline */
Nicolas Palix4193d4f2009-07-29 14:10:10 +020074 struct hv_netvsc_packet Packet;
Hank Janssenfceaf242009-07-13 15:34:54 -070075 PAGE_BUFFER Buffer;
Bill Pemberton454f18a2009-07-27 16:47:24 -040076 /* FIXME: We assumed a fixed size request here. */
Hank Janssenfceaf242009-07-13 15:34:54 -070077 RNDIS_MESSAGE RequestMessage;
78} RNDIS_REQUEST;
79
80
81typedef struct _RNDIS_FILTER_PACKET {
82 void *CompletionContext;
83 PFN_ON_SENDRECVCOMPLETION OnCompletion;
84
85 RNDIS_MESSAGE Message;
86} RNDIS_FILTER_PACKET;
87
Bill Pemberton454f18a2009-07-27 16:47:24 -040088
89/* Internal routines */
90
Hank Janssenfceaf242009-07-13 15:34:54 -070091static int
92RndisFilterSendRequest(
93 RNDIS_DEVICE *Device,
94 RNDIS_REQUEST *Request
95 );
96
97static void
98RndisFilterReceiveResponse(
99 RNDIS_DEVICE *Device,
100 RNDIS_MESSAGE *Response
101 );
102
103static void
104RndisFilterReceiveIndicateStatus(
105 RNDIS_DEVICE *Device,
106 RNDIS_MESSAGE *Response
107 );
108
109static void
110RndisFilterReceiveData(
111 RNDIS_DEVICE *Device,
112 RNDIS_MESSAGE *Message,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200113 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700114 );
115
116static int
117RndisFilterOnReceive(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200118 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200119 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700120 );
121
122static int
123RndisFilterQueryDevice(
124 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700125 u32 Oid,
Greg Kroah-Hartmane20f6832009-07-14 15:07:21 -0700126 void *Result,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700127 u32 *ResultSize
Hank Janssenfceaf242009-07-13 15:34:54 -0700128 );
129
130static inline int
131RndisFilterQueryDeviceMac(
132 RNDIS_DEVICE *Device
133 );
134
135static inline int
136RndisFilterQueryDeviceLinkStatus(
137 RNDIS_DEVICE *Device
138 );
139
140static int
141RndisFilterSetPacketFilter(
142 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700143 u32 NewFilter
Hank Janssenfceaf242009-07-13 15:34:54 -0700144 );
145
146static int
147RndisFilterInitDevice(
148 RNDIS_DEVICE *Device
149 );
150
151static int
152RndisFilterOpenDevice(
153 RNDIS_DEVICE *Device
154 );
155
156static int
157RndisFilterCloseDevice(
158 RNDIS_DEVICE *Device
159 );
160
161static int
162RndisFilterOnDeviceAdd(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200163 struct hv_device *Device,
Hank Janssenfceaf242009-07-13 15:34:54 -0700164 void *AdditionalInfo
165 );
166
167static int
168RndisFilterOnDeviceRemove(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200169 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -0700170 );
171
172static void
173RndisFilterOnCleanup(
Nicolas Palix775ef252009-07-29 14:09:45 +0200174 struct hv_driver *Driver
Hank Janssenfceaf242009-07-13 15:34:54 -0700175 );
176
177static int
178RndisFilterOnOpen(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200179 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -0700180 );
181
182static int
183RndisFilterOnClose(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200184 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -0700185 );
186
187static int
188RndisFilterOnSend(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200189 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200190 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700191 );
192
193static void
194RndisFilterOnSendCompletion(
195 void *Context
196 );
197
198static void
199RndisFilterOnSendRequestCompletion(
200 void *Context
201 );
202
Hank Janssenfceaf242009-07-13 15:34:54 -0700203
Bill Pemberton454f18a2009-07-27 16:47:24 -0400204/* Global var */
205
206
207/* The one and only */
Greg Kroah-Hartmanbd1de702009-07-29 09:04:51 -0700208static RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
Hank Janssenfceaf242009-07-13 15:34:54 -0700209
210static inline RNDIS_DEVICE* GetRndisDevice(void)
211{
212 RNDIS_DEVICE *device;
213
Greg Kroah-Hartmane276a3a2009-07-15 12:47:43 -0700214 device = kzalloc(sizeof(RNDIS_DEVICE), GFP_KERNEL);
Hank Janssenfceaf242009-07-13 15:34:54 -0700215 if (!device)
216 {
217 return NULL;
218 }
219
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700220 spin_lock_init(&device->request_lock);
Hank Janssenfceaf242009-07-13 15:34:54 -0700221
222 INITIALIZE_LIST_HEAD(&device->RequestList);
223
224 device->State = RNDIS_DEV_UNINITIALIZED;
225
226 return device;
227}
228
229static inline void PutRndisDevice(RNDIS_DEVICE *Device)
230{
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700231 kfree(Device);
Hank Janssenfceaf242009-07-13 15:34:54 -0700232}
233
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700234static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, u32 MessageType, u32 MessageLength)
Hank Janssenfceaf242009-07-13 15:34:54 -0700235{
236 RNDIS_REQUEST *request;
237 RNDIS_MESSAGE *rndisMessage;
238 RNDIS_SET_REQUEST *set;
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700239 unsigned long flags;
Hank Janssenfceaf242009-07-13 15:34:54 -0700240
Greg Kroah-Hartmane276a3a2009-07-15 12:47:43 -0700241 request = kzalloc(sizeof(RNDIS_REQUEST), GFP_KERNEL);
Hank Janssenfceaf242009-07-13 15:34:54 -0700242 if (!request)
243 {
244 return NULL;
245 }
246
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700247 request->WaitEvent = osd_WaitEventCreate();
Hank Janssenfceaf242009-07-13 15:34:54 -0700248 if (!request->WaitEvent)
249 {
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700250 kfree(request);
Hank Janssenfceaf242009-07-13 15:34:54 -0700251 return NULL;
252 }
253
254 rndisMessage = &request->RequestMessage;
255 rndisMessage->NdisMessageType = MessageType;
256 rndisMessage->MessageLength = MessageLength;
257
Bill Pemberton454f18a2009-07-27 16:47:24 -0400258 /* 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 */
Hank Janssenfceaf242009-07-13 15:34:54 -0700260 set = &rndisMessage->Message.SetRequest;
Bill Pembertonf4888412009-07-29 17:00:12 -0400261 set->RequestId = atomic_inc_return(&Device->NewRequestId);
Hank Janssenfceaf242009-07-13 15:34:54 -0700262
Bill Pemberton454f18a2009-07-27 16:47:24 -0400263 /* Add to the request list */
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700264 spin_lock_irqsave(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700265 INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700266 spin_unlock_irqrestore(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700267
268 return request;
269}
270
271static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
272{
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700273 unsigned long flags;
274
275 spin_lock_irqsave(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700276 REMOVE_ENTRY_LIST(&Request->ListEntry);
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700277 spin_unlock_irqrestore(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700278
Bill Pemberton420beac2009-07-29 17:00:10 -0400279 kfree(Request->WaitEvent);
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700280 kfree(Request);
Hank Janssenfceaf242009-07-13 15:34:54 -0700281}
282
283static inline void DumpRndisMessage(RNDIS_MESSAGE *RndisMessage)
284{
285 switch (RndisMessage->NdisMessageType)
286 {
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;
298
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;
311
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;
320
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;
327
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;
335
336 default:
337 DPRINT_DBG(NETVSC, "0x%x (len %u)",
338 RndisMessage->NdisMessageType,
339 RndisMessage->MessageLength);
340 break;
341 }
342}
343
344static int
345RndisFilterSendRequest(
346 RNDIS_DEVICE *Device,
347 RNDIS_REQUEST *Request
348 )
349{
350 int ret=0;
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200351 struct hv_netvsc_packet *packet;
Hank Janssenfceaf242009-07-13 15:34:54 -0700352
353 DPRINT_ENTER(NETVSC);
354
Bill Pemberton454f18a2009-07-27 16:47:24 -0400355 /* Setup the packet to send it */
Hank Janssenfceaf242009-07-13 15:34:54 -0700356 packet = &Request->Packet;
357
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700358 packet->IsDataPacket = false;
Hank Janssenfceaf242009-07-13 15:34:54 -0700359 packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
360 packet->PageBufferCount = 1;
361
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700362 packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >> PAGE_SHIFT;
Hank Janssenfceaf242009-07-13 15:34:54 -0700363 packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700364 packet->PageBuffers[0].Offset = (unsigned long)&Request->RequestMessage & (PAGE_SIZE -1);
Hank Janssenfceaf242009-07-13 15:34:54 -0700365
Bill Pemberton454f18a2009-07-27 16:47:24 -0400366 packet->Completion.Send.SendCompletionContext = Request;/* packet; */
Hank Janssenfceaf242009-07-13 15:34:54 -0700367 packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700368 packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
Hank Janssenfceaf242009-07-13 15:34:54 -0700369
370 ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
371 DPRINT_EXIT(NETVSC);
372 return ret;
373}
374
375
376static void
377RndisFilterReceiveResponse(
378 RNDIS_DEVICE *Device,
379 RNDIS_MESSAGE *Response
380 )
381{
382 LIST_ENTRY *anchor;
383 LIST_ENTRY *curr;
384 RNDIS_REQUEST *request=NULL;
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700385 bool found = false;
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700386 unsigned long flags;
Hank Janssenfceaf242009-07-13 15:34:54 -0700387
388 DPRINT_ENTER(NETVSC);
389
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700390 spin_lock_irqsave(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700391 ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList)
392 {
393 request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
394
Bill Pemberton454f18a2009-07-27 16:47:24 -0400395 /* All request/response message contains RequestId as the 1st field */
Hank Janssenfceaf242009-07-13 15:34:54 -0700396 if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
397 {
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);
400
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700401 found = true;
Hank Janssenfceaf242009-07-13 15:34:54 -0700402 break;
403 }
404 }
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700405 spin_unlock_irqrestore(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700406
407 if (found)
408 {
409 if (Response->MessageLength <= sizeof(RNDIS_MESSAGE))
410 {
411 memcpy(&request->ResponseMessage, Response, Response->MessageLength);
412 }
413 else
414 {
Greg Kroah-Hartmanb7d7ae62009-07-28 16:18:05 -0700415 DPRINT_ERR(NETVSC, "rndis response buffer overflow detected (size %u max %zu)", Response->MessageLength, sizeof(RNDIS_FILTER_PACKET));
Hank Janssenfceaf242009-07-13 15:34:54 -0700416
Bill Pemberton454f18a2009-07-27 16:47:24 -0400417 if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) /* does not have a request id field */
Hank Janssenfceaf242009-07-13 15:34:54 -0700418 {
419 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
420 }
421 else
422 {
423 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
424 }
425 }
426
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700427 osd_WaitEventSet(request->WaitEvent);
Hank Janssenfceaf242009-07-13 15:34:54 -0700428 }
429 else
430 {
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);
433 }
434
435 DPRINT_EXIT(NETVSC);
436}
437
438static void
439RndisFilterReceiveIndicateStatus(
440 RNDIS_DEVICE *Device,
441 RNDIS_MESSAGE *Response
442 )
443{
444 RNDIS_INDICATE_STATUS *indicate = &Response->Message.IndicateStatus;
445
446 if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT)
447 {
448 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
449 }
450 else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT)
451 {
452 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
453 }
454 else
455 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400456 /* TODO: */
Hank Janssenfceaf242009-07-13 15:34:54 -0700457 }
458}
459
460static void
461RndisFilterReceiveData(
462 RNDIS_DEVICE *Device,
463 RNDIS_MESSAGE *Message,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200464 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700465 )
466{
467 RNDIS_PACKET *rndisPacket;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700468 u32 dataOffset;
Hank Janssenfceaf242009-07-13 15:34:54 -0700469
470 DPRINT_ENTER(NETVSC);
471
Bill Pemberton454f18a2009-07-27 16:47:24 -0400472 /* empty ethernet frame ?? */
Hank Janssenfceaf242009-07-13 15:34:54 -0700473 ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(RNDIS_PACKET));
474
475 rndisPacket = &Message->Message.Packet;
476
Bill Pemberton454f18a2009-07-27 16:47:24 -0400477 /* FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this */
478 /* netvsc packet (ie TotalDataBufferLength != MessageLength) */
Hank Janssenfceaf242009-07-13 15:34:54 -0700479
Bill Pemberton454f18a2009-07-27 16:47:24 -0400480 /* Remove the rndis header and pass it back up the stack */
Hank Janssenfceaf242009-07-13 15:34:54 -0700481 dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
482
483 Packet->TotalDataBufferLength -= dataOffset;
484 Packet->PageBuffers[0].Offset += dataOffset;
485 Packet->PageBuffers[0].Length -= dataOffset;
486
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700487 Packet->IsDataPacket = true;
Hank Janssenfceaf242009-07-13 15:34:54 -0700488
489 gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device, Packet);
490
491 DPRINT_EXIT(NETVSC);
492}
493
494static int
495RndisFilterOnReceive(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200496 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200497 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700498 )
499{
Bill Pembertond1af1db72009-07-27 16:47:44 -0400500 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -0700501 RNDIS_DEVICE *rndisDevice;
502 RNDIS_MESSAGE rndisMessage;
503 RNDIS_MESSAGE *rndisHeader;
504
505 DPRINT_ENTER(NETVSC);
506
507 ASSERT(netDevice);
Bill Pemberton454f18a2009-07-27 16:47:24 -0400508 /* Make sure the rndis device state is initialized */
Hank Janssenfceaf242009-07-13 15:34:54 -0700509 if (!netDevice->Extension)
510 {
511 DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
512 DPRINT_EXIT(NETVSC);
513 return -1;
514 }
515
516 rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
517 if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED)
518 {
519 DPRINT_ERR(NETVSC, "got rndis message but rndis device uninitialized...dropping this message!");
520 DPRINT_EXIT(NETVSC);
521 return -1;
522 }
523
Bill Pemberton45da89e2009-07-29 17:00:15 -0400524 rndisHeader = (RNDIS_MESSAGE *)kmap_atomic(pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
Hank Janssenfceaf242009-07-13 15:34:54 -0700525
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700526 rndisHeader = (void*)((unsigned long)rndisHeader + Packet->PageBuffers[0].Offset);
Hank Janssenfceaf242009-07-13 15:34:54 -0700527
Bill Pemberton454f18a2009-07-27 16:47:24 -0400528 /* 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 */
Hank Janssenfceaf242009-07-13 15:34:54 -0700531#if 0
532 if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
533 {
Bill Pemberton45da89e2009-07-29 17:00:15 -0400534 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
Hank Janssenfceaf242009-07-13 15:34:54 -0700535
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;
540 }
541#endif
542
543 if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE)))
544 {
Greg Kroah-Hartmanb7d7ae62009-07-28 16:18:05 -0700545 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %zu)...marking it an error!",
Hank Janssenfceaf242009-07-13 15:34:54 -0700546 rndisHeader->MessageLength, sizeof(RNDIS_MESSAGE));
547 }
548
549 memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(RNDIS_MESSAGE))?sizeof(RNDIS_MESSAGE):rndisHeader->MessageLength);
550
Bill Pemberton45da89e2009-07-29 17:00:15 -0400551 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
Hank Janssenfceaf242009-07-13 15:34:54 -0700552
553 DumpRndisMessage(&rndisMessage);
554
555 switch (rndisMessage.NdisMessageType)
556 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400557 /* data msg */
Hank Janssenfceaf242009-07-13 15:34:54 -0700558 case REMOTE_NDIS_PACKET_MSG:
559 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
560 break;
561
Bill Pemberton454f18a2009-07-27 16:47:24 -0400562 /* completion msgs */
Hank Janssenfceaf242009-07-13 15:34:54 -0700563 case REMOTE_NDIS_INITIALIZE_CMPLT:
564 case REMOTE_NDIS_QUERY_CMPLT:
565 case REMOTE_NDIS_SET_CMPLT:
Bill Pemberton454f18a2009-07-27 16:47:24 -0400566 /* case REMOTE_NDIS_RESET_CMPLT: */
567 /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
Hank Janssenfceaf242009-07-13 15:34:54 -0700568 RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
569 break;
570
Bill Pemberton454f18a2009-07-27 16:47:24 -0400571 /* notification msgs */
Hank Janssenfceaf242009-07-13 15:34:54 -0700572 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;
578 }
579
580 DPRINT_EXIT(NETVSC);
581 return 0;
582}
583
584
585static int
586RndisFilterQueryDevice(
587 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700588 u32 Oid,
Greg Kroah-Hartmane20f6832009-07-14 15:07:21 -0700589 void *Result,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700590 u32 *ResultSize
Hank Janssenfceaf242009-07-13 15:34:54 -0700591 )
592{
593 RNDIS_REQUEST *request;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700594 u32 inresultSize = *ResultSize;
Hank Janssenfceaf242009-07-13 15:34:54 -0700595 RNDIS_QUERY_REQUEST *query;
596 RNDIS_QUERY_COMPLETE *queryComplete;
597 int ret=0;
598
599 DPRINT_ENTER(NETVSC);
600
601 ASSERT(Result);
602
603 *ResultSize = 0;
604 request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST));
605 if (!request)
606 {
607 ret = -1;
608 goto Cleanup;
609 }
610
Bill Pemberton454f18a2009-07-27 16:47:24 -0400611 /* Setup the rndis query */
Hank Janssenfceaf242009-07-13 15:34:54 -0700612 query = &request->RequestMessage.Message.QueryRequest;
613 query->Oid = Oid;
614 query->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
615 query->InformationBufferLength = 0;
616 query->DeviceVcHandle = 0;
617
618 ret = RndisFilterSendRequest(Device, request);
619 if (ret != 0)
620 {
621 goto Cleanup;
622 }
623
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700624 osd_WaitEventWait(request->WaitEvent);
Hank Janssenfceaf242009-07-13 15:34:54 -0700625
Bill Pemberton454f18a2009-07-27 16:47:24 -0400626 /* Copy the response back */
Hank Janssenfceaf242009-07-13 15:34:54 -0700627 queryComplete = &request->ResponseMessage.Message.QueryComplete;
628
629 if (queryComplete->InformationBufferLength > inresultSize)
630 {
631 ret = -1;
632 goto Cleanup;
633 }
634
635 memcpy(Result,
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700636 (void*)((unsigned long)queryComplete + queryComplete->InformationBufferOffset),
Hank Janssenfceaf242009-07-13 15:34:54 -0700637 queryComplete->InformationBufferLength);
638
639 *ResultSize = queryComplete->InformationBufferLength;
640
641Cleanup:
642 if (request)
643 {
644 PutRndisRequest(Device, request);
645 }
646 DPRINT_EXIT(NETVSC);
647
648 return ret;
649}
650
651static inline int
652RndisFilterQueryDeviceMac(
653 RNDIS_DEVICE *Device
654 )
655{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700656 u32 size=HW_MACADDR_LEN;
Hank Janssenfceaf242009-07-13 15:34:54 -0700657
658 return RndisFilterQueryDevice(Device,
659 RNDIS_OID_802_3_PERMANENT_ADDRESS,
660 Device->HwMacAddr,
661 &size);
662}
663
664static inline int
665RndisFilterQueryDeviceLinkStatus(
666 RNDIS_DEVICE *Device
667 )
668{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700669 u32 size=sizeof(u32);
Hank Janssenfceaf242009-07-13 15:34:54 -0700670
671 return RndisFilterQueryDevice(Device,
672 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
673 &Device->LinkStatus,
674 &size);
675}
676
677static int
678RndisFilterSetPacketFilter(
679 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700680 u32 NewFilter
Hank Janssenfceaf242009-07-13 15:34:54 -0700681 )
682{
683 RNDIS_REQUEST *request;
684 RNDIS_SET_REQUEST *set;
685 RNDIS_SET_COMPLETE *setComplete;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700686 u32 status;
Hank Janssenfceaf242009-07-13 15:34:54 -0700687 int ret;
688
689 DPRINT_ENTER(NETVSC);
690
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700691 ASSERT(RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(u32) <= sizeof(RNDIS_MESSAGE));
Hank Janssenfceaf242009-07-13 15:34:54 -0700692
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700693 request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + sizeof(u32));
Hank Janssenfceaf242009-07-13 15:34:54 -0700694 if (!request)
695 {
696 ret = -1;
697 goto Cleanup;
698 }
699
Bill Pemberton454f18a2009-07-27 16:47:24 -0400700 /* Setup the rndis set */
Hank Janssenfceaf242009-07-13 15:34:54 -0700701 set = &request->RequestMessage.Message.SetRequest;
702 set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700703 set->InformationBufferLength = sizeof(u32);
Hank Janssenfceaf242009-07-13 15:34:54 -0700704 set->InformationBufferOffset = sizeof(RNDIS_SET_REQUEST);
705
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700706 memcpy((void*)(unsigned long)set + sizeof(RNDIS_SET_REQUEST), &NewFilter, sizeof(u32));
Hank Janssenfceaf242009-07-13 15:34:54 -0700707
708 ret = RndisFilterSendRequest(Device, request);
709 if (ret != 0)
710 {
711 goto Cleanup;
712 }
713
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700714 ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
Hank Janssenfceaf242009-07-13 15:34:54 -0700715 if (!ret)
716 {
717 ret = -1;
718 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
Bill Pemberton454f18a2009-07-27 16:47:24 -0400719 /* We cant deallocate the request since we may still receive a send completion for it. */
Hank Janssenfceaf242009-07-13 15:34:54 -0700720 goto Exit;
721 }
722 else
723 {
724 if (ret > 0)
725 {
726 ret = 0;
727 }
728 setComplete = &request->ResponseMessage.Message.SetComplete;
729 status = setComplete->Status;
730 }
731
732Cleanup:
733 if (request)
734 {
735 PutRndisRequest(Device, request);
736 }
737Exit:
738 DPRINT_EXIT(NETVSC);
739
740 return ret;
741}
742
743int
744RndisFilterInit(
745 NETVSC_DRIVER_OBJECT *Driver
746 )
747{
748 DPRINT_ENTER(NETVSC);
749
Greg Kroah-Hartmanb7d7ae62009-07-28 16:18:05 -0700750 DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %zd", sizeof(RNDIS_FILTER_PACKET));
Hank Janssenfceaf242009-07-13 15:34:54 -0700751
752 Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
Bill Pemberton454f18a2009-07-27 16:47:24 -0400753 Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
Hank Janssenfceaf242009-07-13 15:34:54 -0700754
Bill Pemberton454f18a2009-07-27 16:47:24 -0400755 /* Driver->Context = rndisDriver; */
Hank Janssenfceaf242009-07-13 15:34:54 -0700756
757 memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
758
759 /*rndisDriver->Driver = Driver;
760
761 ASSERT(Driver->OnLinkStatusChanged);
762 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
763
Bill Pemberton454f18a2009-07-27 16:47:24 -0400764 /* Save the original dispatch handlers before we override it */
Hank Janssenfceaf242009-07-13 15:34:54 -0700765 gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
766 gRndisFilter.InnerDriver.Base.OnDeviceRemove = Driver->Base.OnDeviceRemove;
767 gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
768
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;
774
Bill Pemberton454f18a2009-07-27 16:47:24 -0400775 /* Override */
Hank Janssenfceaf242009-07-13 15:34:54 -0700776 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;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400782 /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
Hank Janssenfceaf242009-07-13 15:34:54 -0700783 Driver->OnReceiveCallback = RndisFilterOnReceive;
784
785 DPRINT_EXIT(NETVSC);
786
787 return 0;
788}
789
790static int
791RndisFilterInitDevice(
792 RNDIS_DEVICE *Device
793 )
794{
795 RNDIS_REQUEST *request;
796 RNDIS_INITIALIZE_REQUEST *init;
797 RNDIS_INITIALIZE_COMPLETE *initComplete;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700798 u32 status;
Hank Janssenfceaf242009-07-13 15:34:54 -0700799 int ret;
800
801 DPRINT_ENTER(NETVSC);
802
803 request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST));
804 if (!request)
805 {
806 ret = -1;
807 goto Cleanup;
808 }
809
Bill Pemberton454f18a2009-07-27 16:47:24 -0400810 /* Setup the rndis set */
Hank Janssenfceaf242009-07-13 15:34:54 -0700811 init = &request->RequestMessage.Message.InitializeRequest;
812 init->MajorVersion = RNDIS_MAJOR_VERSION;
813 init->MinorVersion = RNDIS_MINOR_VERSION;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400814 init->MaxTransferSize = 2048; /* FIXME: Use 1536 - rounded ethernet frame size */
Hank Janssenfceaf242009-07-13 15:34:54 -0700815
816 Device->State = RNDIS_DEV_INITIALIZING;
817
818 ret = RndisFilterSendRequest(Device, request);
819 if (ret != 0)
820 {
821 Device->State = RNDIS_DEV_UNINITIALIZED;
822 goto Cleanup;
823 }
824
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700825 osd_WaitEventWait(request->WaitEvent);
Hank Janssenfceaf242009-07-13 15:34:54 -0700826
827 initComplete = &request->ResponseMessage.Message.InitializeComplete;
828 status = initComplete->Status;
829 if (status == RNDIS_STATUS_SUCCESS)
830 {
831 Device->State = RNDIS_DEV_INITIALIZED;
832 ret = 0;
833 }
834 else
835 {
836 Device->State = RNDIS_DEV_UNINITIALIZED;
837 ret = -1;
838 }
839
840Cleanup:
841 if (request)
842 {
843 PutRndisRequest(Device, request);
844 }
845 DPRINT_EXIT(NETVSC);
846
847 return ret;
848}
849
850static void
851RndisFilterHaltDevice(
852 RNDIS_DEVICE *Device
853 )
854{
855 RNDIS_REQUEST *request;
856 RNDIS_HALT_REQUEST *halt;
857
858 DPRINT_ENTER(NETVSC);
859
Bill Pemberton454f18a2009-07-27 16:47:24 -0400860 /* Attempt to do a rndis device halt */
Hank Janssenfceaf242009-07-13 15:34:54 -0700861 request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST));
862 if (!request)
863 {
864 goto Cleanup;
865 }
866
Bill Pemberton454f18a2009-07-27 16:47:24 -0400867 /* Setup the rndis set */
Hank Janssenfceaf242009-07-13 15:34:54 -0700868 halt = &request->RequestMessage.Message.HaltRequest;
Bill Pembertonf4888412009-07-29 17:00:12 -0400869 halt->RequestId = atomic_inc_return(&Device->NewRequestId);
Hank Janssenfceaf242009-07-13 15:34:54 -0700870
Bill Pemberton454f18a2009-07-27 16:47:24 -0400871 /* Ignore return since this msg is optional. */
Hank Janssenfceaf242009-07-13 15:34:54 -0700872 RndisFilterSendRequest(Device, request);
873
874 Device->State = RNDIS_DEV_UNINITIALIZED;
875
876Cleanup:
877 if (request)
878 {
879 PutRndisRequest(Device, request);
880 }
881 DPRINT_EXIT(NETVSC);
882 return;
883}
884
885
886static int
887RndisFilterOpenDevice(
888 RNDIS_DEVICE *Device
889 )
890{
891 int ret=0;
892
893 DPRINT_ENTER(NETVSC);
894
895 if (Device->State != RNDIS_DEV_INITIALIZED)
896 return 0;
897
898 ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
899 if (ret == 0)
900 {
901 Device->State = RNDIS_DEV_DATAINITIALIZED;
902 }
903
904 DPRINT_EXIT(NETVSC);
905 return ret;
906}
907
908static int
909RndisFilterCloseDevice(
910 RNDIS_DEVICE *Device
911 )
912{
913 int ret;
914
915 DPRINT_ENTER(NETVSC);
916
917 if (Device->State != RNDIS_DEV_DATAINITIALIZED)
918 return 0;
919
920 ret = RndisFilterSetPacketFilter(Device, 0);
921 if (ret == 0)
922 {
923 Device->State = RNDIS_DEV_INITIALIZED;
924 }
925
926 DPRINT_EXIT(NETVSC);
927
928 return ret;
929}
930
931
Greg Kroah-Hartmanbd1de702009-07-29 09:04:51 -0700932static int
Hank Janssenfceaf242009-07-13 15:34:54 -0700933RndisFilterOnDeviceAdd(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200934 struct hv_device *Device,
Hank Janssenfceaf242009-07-13 15:34:54 -0700935 void *AdditionalInfo
936 )
937{
938 int ret;
Bill Pembertond1af1db72009-07-27 16:47:44 -0400939 struct NETVSC_DEVICE *netDevice;
Hank Janssenfceaf242009-07-13 15:34:54 -0700940 RNDIS_DEVICE *rndisDevice;
941 NETVSC_DEVICE_INFO *deviceInfo = (NETVSC_DEVICE_INFO*)AdditionalInfo;
942
943 DPRINT_ENTER(NETVSC);
944
Hank Janssenfceaf242009-07-13 15:34:54 -0700945 rndisDevice = GetRndisDevice();
946 if (!rndisDevice)
947 {
948 DPRINT_EXIT(NETVSC);
949 return -1;
950 }
951
952 DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
953
Bill Pemberton454f18a2009-07-27 16:47:24 -0400954 /* 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 */
Hank Janssenfceaf242009-07-13 15:34:54 -0700957 ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
958 if (ret != 0)
959 {
960 PutRndisDevice(rndisDevice);
961 DPRINT_EXIT(NETVSC);
962 return ret;
963 }
964
Bill Pemberton454f18a2009-07-27 16:47:24 -0400965
966 /* Initialize the rndis device */
967
Bill Pembertond1af1db72009-07-27 16:47:44 -0400968 netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -0700969 ASSERT(netDevice);
970 ASSERT(netDevice->Device);
971
972 netDevice->Extension = rndisDevice;
973 rndisDevice->NetDevice = netDevice;
974
Bill Pemberton454f18a2009-07-27 16:47:24 -0400975 /* Send the rndis initialization message */
Hank Janssenfceaf242009-07-13 15:34:54 -0700976 ret = RndisFilterInitDevice(rndisDevice);
977 if (ret != 0)
978 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400979 /* TODO: If rndis init failed, we will need to shut down the channel */
Hank Janssenfceaf242009-07-13 15:34:54 -0700980 }
981
Bill Pemberton454f18a2009-07-27 16:47:24 -0400982 /* Get the mac address */
Hank Janssenfceaf242009-07-13 15:34:54 -0700983 ret = RndisFilterQueryDeviceMac(rndisDevice);
984 if (ret != 0)
985 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400986 /* TODO: shutdown rndis device and the channel */
Hank Janssenfceaf242009-07-13 15:34:54 -0700987 }
988
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]);
997
998 memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
999
1000 RndisFilterQueryDeviceLinkStatus(rndisDevice);
1001
1002 deviceInfo->LinkState = rndisDevice->LinkStatus;
1003 DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, ((deviceInfo->LinkState)?("down"):("up")));
1004
1005 DPRINT_EXIT(NETVSC);
1006
1007 return ret;
1008}
1009
1010
1011static int
1012RndisFilterOnDeviceRemove(
Nicolas Palix3d3b5512009-07-28 17:32:53 +02001013 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -07001014 )
1015{
Bill Pembertond1af1db72009-07-27 16:47:44 -04001016 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -07001017 RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
1018
1019 DPRINT_ENTER(NETVSC);
1020
Bill Pemberton454f18a2009-07-27 16:47:24 -04001021 /* Halt and release the rndis device */
Hank Janssenfceaf242009-07-13 15:34:54 -07001022 RndisFilterHaltDevice(rndisDevice);
1023
1024 PutRndisDevice(rndisDevice);
1025 netDevice->Extension = NULL;
1026
Bill Pemberton454f18a2009-07-27 16:47:24 -04001027 /* Pass control to inner driver to remove the device */
Hank Janssenfceaf242009-07-13 15:34:54 -07001028 gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
1029
1030 DPRINT_EXIT(NETVSC);
1031
1032 return 0;
1033}
1034
1035
1036static void
1037RndisFilterOnCleanup(
Nicolas Palix775ef252009-07-29 14:09:45 +02001038 struct hv_driver *Driver
Hank Janssenfceaf242009-07-13 15:34:54 -07001039 )
1040{
1041 DPRINT_ENTER(NETVSC);
1042
1043 DPRINT_EXIT(NETVSC);
1044}
1045
1046static int
1047RndisFilterOnOpen(
Nicolas Palix3d3b5512009-07-28 17:32:53 +02001048 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -07001049 )
1050{
1051 int ret;
Bill Pembertond1af1db72009-07-27 16:47:44 -04001052 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -07001053
1054 DPRINT_ENTER(NETVSC);
1055
1056 ASSERT(netDevice);
1057 ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
1058
1059 DPRINT_EXIT(NETVSC);
1060
1061 return ret;
1062}
1063
1064static int
1065RndisFilterOnClose(
Nicolas Palix3d3b5512009-07-28 17:32:53 +02001066 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -07001067 )
1068{
1069 int ret;
Bill Pembertond1af1db72009-07-27 16:47:44 -04001070 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -07001071
1072 DPRINT_ENTER(NETVSC);
1073
1074 ASSERT(netDevice);
1075 ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
1076
1077 DPRINT_EXIT(NETVSC);
1078
1079 return ret;
1080}
1081
1082
1083static int
1084RndisFilterOnSend(
Nicolas Palix3d3b5512009-07-28 17:32:53 +02001085 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +02001086 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -07001087 )
1088{
1089 int ret=0;
1090 RNDIS_FILTER_PACKET *filterPacket;
1091 RNDIS_MESSAGE *rndisMessage;
1092 RNDIS_PACKET *rndisPacket;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -07001093 u32 rndisMessageSize;
Hank Janssenfceaf242009-07-13 15:34:54 -07001094
1095 DPRINT_ENTER(NETVSC);
1096
Bill Pemberton454f18a2009-07-27 16:47:24 -04001097 /* Add the rndis header */
Hank Janssenfceaf242009-07-13 15:34:54 -07001098 filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
1099 ASSERT(filterPacket);
1100
1101 memset(filterPacket, 0, sizeof(RNDIS_FILTER_PACKET));
1102
1103 rndisMessage = &filterPacket->Message;
1104 rndisMessageSize = RNDIS_MESSAGE_SIZE(RNDIS_PACKET);
1105
1106 rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
1107 rndisMessage->MessageLength = Packet->TotalDataBufferLength + rndisMessageSize;
1108
1109 rndisPacket = &rndisMessage->Message.Packet;
1110 rndisPacket->DataOffset = sizeof(RNDIS_PACKET);
1111 rndisPacket->DataLength = Packet->TotalDataBufferLength;
1112
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -07001113 Packet->IsDataPacket = true;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -07001114 Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -07001115 Packet->PageBuffers[0].Offset = (unsigned long)rndisMessage & (PAGE_SIZE-1);
Hank Janssenfceaf242009-07-13 15:34:54 -07001116 Packet->PageBuffers[0].Length = rndisMessageSize;
1117
Bill Pemberton454f18a2009-07-27 16:47:24 -04001118 /* Save the packet send completion and context */
Hank Janssenfceaf242009-07-13 15:34:54 -07001119 filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
1120 filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
1121
Bill Pemberton454f18a2009-07-27 16:47:24 -04001122 /* Use ours */
Hank Janssenfceaf242009-07-13 15:34:54 -07001123 Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
1124 Packet->Completion.Send.SendCompletionContext = filterPacket;
1125
1126 ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
1127 if (ret != 0)
1128 {
Bill Pemberton454f18a2009-07-27 16:47:24 -04001129 /* Reset the completion to originals to allow retries from above */
Hank Janssenfceaf242009-07-13 15:34:54 -07001130 Packet->Completion.Send.OnSendCompletion = filterPacket->OnCompletion;
1131 Packet->Completion.Send.SendCompletionContext = filterPacket->CompletionContext;
1132 }
1133
1134 DPRINT_EXIT(NETVSC);
1135
1136 return ret;
1137}
1138
1139static void
1140RndisFilterOnSendCompletion(
1141 void *Context)
1142{
1143 RNDIS_FILTER_PACKET *filterPacket = (RNDIS_FILTER_PACKET *)Context;
1144
1145 DPRINT_ENTER(NETVSC);
1146
Bill Pemberton454f18a2009-07-27 16:47:24 -04001147 /* Pass it back to the original handler */
Hank Janssenfceaf242009-07-13 15:34:54 -07001148 filterPacket->OnCompletion(filterPacket->CompletionContext);
1149
1150 DPRINT_EXIT(NETVSC);
1151}
1152
1153
1154static void
1155RndisFilterOnSendRequestCompletion(
1156 void *Context
1157 )
1158{
1159 DPRINT_ENTER(NETVSC);
1160
Bill Pemberton454f18a2009-07-27 16:47:24 -04001161 /* Noop */
Hank Janssenfceaf242009-07-13 15:34:54 -07001162 DPRINT_EXIT(NETVSC);
1163}