blob: 3a444800f94b5ad10fdc92e9fe6dbcb0e004b561 [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-Hartman4983b392009-08-19 16:14:47 -070029#include "osd.h"
Greg Kroah-Hartmanc86f3e22009-07-14 10:59:56 -070030#include "include/logging.h"
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 */
Greg Kroah-Hartman7e23a6e2009-08-27 15:58:15 -070040 struct netvsc_driver InnerDriver;
Hank Janssenfceaf242009-07-13 15:34:54 -070041
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 */
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -070071 struct rndis_message ResponseMessage;
Hank Janssenfceaf242009-07-13 15:34:54 -070072
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;
Greg Kroah-Hartmanee3d7dd2009-08-20 12:17:36 -070075 struct hv_page_buffer Buffer;
Bill Pemberton454f18a2009-07-27 16:47:24 -040076 /* FIXME: We assumed a fixed size request here. */
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -070077 struct rndis_message RequestMessage;
Hank Janssenfceaf242009-07-13 15:34:54 -070078} RNDIS_REQUEST;
79
80
81typedef struct _RNDIS_FILTER_PACKET {
82 void *CompletionContext;
83 PFN_ON_SENDRECVCOMPLETION OnCompletion;
84
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -070085 struct rndis_message Message;
Hank Janssenfceaf242009-07-13 15:34:54 -070086} 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
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -070097static void RndisFilterReceiveResponse(RNDIS_DEVICE *Device,
98 struct rndis_message *Response);
Hank Janssenfceaf242009-07-13 15:34:54 -070099
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700100static void RndisFilterReceiveIndicateStatus(RNDIS_DEVICE *Device,
101 struct rndis_message *Response);
Hank Janssenfceaf242009-07-13 15:34:54 -0700102
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700103static void RndisFilterReceiveData(RNDIS_DEVICE *Device,
104 struct rndis_message *Message,
105 struct hv_netvsc_packet *Packet);
Hank Janssenfceaf242009-07-13 15:34:54 -0700106
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700107static int RndisFilterOnReceive(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200108 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200109 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700110 );
111
112static int
113RndisFilterQueryDevice(
114 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700115 u32 Oid,
Greg Kroah-Hartmane20f6832009-07-14 15:07:21 -0700116 void *Result,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700117 u32 *ResultSize
Hank Janssenfceaf242009-07-13 15:34:54 -0700118 );
119
120static inline int
121RndisFilterQueryDeviceMac(
122 RNDIS_DEVICE *Device
123 );
124
125static inline int
126RndisFilterQueryDeviceLinkStatus(
127 RNDIS_DEVICE *Device
128 );
129
130static int
131RndisFilterSetPacketFilter(
132 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700133 u32 NewFilter
Hank Janssenfceaf242009-07-13 15:34:54 -0700134 );
135
136static int
137RndisFilterInitDevice(
138 RNDIS_DEVICE *Device
139 );
140
141static int
142RndisFilterOpenDevice(
143 RNDIS_DEVICE *Device
144 );
145
146static int
147RndisFilterCloseDevice(
148 RNDIS_DEVICE *Device
149 );
150
151static int
152RndisFilterOnDeviceAdd(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200153 struct hv_device *Device,
Hank Janssenfceaf242009-07-13 15:34:54 -0700154 void *AdditionalInfo
155 );
156
157static int
158RndisFilterOnDeviceRemove(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200159 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -0700160 );
161
162static void
163RndisFilterOnCleanup(
Nicolas Palix775ef252009-07-29 14:09:45 +0200164 struct hv_driver *Driver
Hank Janssenfceaf242009-07-13 15:34:54 -0700165 );
166
167static int
168RndisFilterOnOpen(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200169 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -0700170 );
171
172static int
173RndisFilterOnClose(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200174 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -0700175 );
176
177static int
178RndisFilterOnSend(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200179 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200180 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700181 );
182
183static void
184RndisFilterOnSendCompletion(
185 void *Context
186 );
187
188static void
189RndisFilterOnSendRequestCompletion(
190 void *Context
191 );
192
Hank Janssenfceaf242009-07-13 15:34:54 -0700193
Bill Pemberton454f18a2009-07-27 16:47:24 -0400194/* Global var */
195
196
197/* The one and only */
Greg Kroah-Hartmanbd1de702009-07-29 09:04:51 -0700198static RNDIS_FILTER_DRIVER_OBJECT gRndisFilter;
Hank Janssenfceaf242009-07-13 15:34:54 -0700199
200static inline RNDIS_DEVICE* GetRndisDevice(void)
201{
202 RNDIS_DEVICE *device;
203
Greg Kroah-Hartmane276a3a2009-07-15 12:47:43 -0700204 device = kzalloc(sizeof(RNDIS_DEVICE), GFP_KERNEL);
Hank Janssenfceaf242009-07-13 15:34:54 -0700205 if (!device)
206 {
207 return NULL;
208 }
209
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700210 spin_lock_init(&device->request_lock);
Hank Janssenfceaf242009-07-13 15:34:54 -0700211
212 INITIALIZE_LIST_HEAD(&device->RequestList);
213
214 device->State = RNDIS_DEV_UNINITIALIZED;
215
216 return device;
217}
218
219static inline void PutRndisDevice(RNDIS_DEVICE *Device)
220{
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700221 kfree(Device);
Hank Janssenfceaf242009-07-13 15:34:54 -0700222}
223
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700224static inline RNDIS_REQUEST* GetRndisRequest(RNDIS_DEVICE *Device, u32 MessageType, u32 MessageLength)
Hank Janssenfceaf242009-07-13 15:34:54 -0700225{
226 RNDIS_REQUEST *request;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700227 struct rndis_message *rndisMessage;
228 struct rndis_set_request *set;
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700229 unsigned long flags;
Hank Janssenfceaf242009-07-13 15:34:54 -0700230
Greg Kroah-Hartmane276a3a2009-07-15 12:47:43 -0700231 request = kzalloc(sizeof(RNDIS_REQUEST), GFP_KERNEL);
Hank Janssenfceaf242009-07-13 15:34:54 -0700232 if (!request)
233 {
234 return NULL;
235 }
236
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700237 request->WaitEvent = osd_WaitEventCreate();
Hank Janssenfceaf242009-07-13 15:34:54 -0700238 if (!request->WaitEvent)
239 {
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700240 kfree(request);
Hank Janssenfceaf242009-07-13 15:34:54 -0700241 return NULL;
242 }
243
244 rndisMessage = &request->RequestMessage;
245 rndisMessage->NdisMessageType = MessageType;
246 rndisMessage->MessageLength = MessageLength;
247
Bill Pemberton454f18a2009-07-27 16:47:24 -0400248 /* Set the request id. This field is always after the rndis header for request/response packet types so */
249 /* we just used the SetRequest as a template */
Hank Janssenfceaf242009-07-13 15:34:54 -0700250 set = &rndisMessage->Message.SetRequest;
Bill Pembertonf4888412009-07-29 17:00:12 -0400251 set->RequestId = atomic_inc_return(&Device->NewRequestId);
Hank Janssenfceaf242009-07-13 15:34:54 -0700252
Bill Pemberton454f18a2009-07-27 16:47:24 -0400253 /* Add to the request list */
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700254 spin_lock_irqsave(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700255 INSERT_TAIL_LIST(&Device->RequestList, &request->ListEntry);
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700256 spin_unlock_irqrestore(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700257
258 return request;
259}
260
261static inline void PutRndisRequest(RNDIS_DEVICE *Device, RNDIS_REQUEST *Request)
262{
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700263 unsigned long flags;
264
265 spin_lock_irqsave(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700266 REMOVE_ENTRY_LIST(&Request->ListEntry);
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700267 spin_unlock_irqrestore(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700268
Bill Pemberton420beac2009-07-29 17:00:10 -0400269 kfree(Request->WaitEvent);
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700270 kfree(Request);
Hank Janssenfceaf242009-07-13 15:34:54 -0700271}
272
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700273static inline void DumpRndisMessage(struct rndis_message *RndisMessage)
Hank Janssenfceaf242009-07-13 15:34:54 -0700274{
275 switch (RndisMessage->NdisMessageType)
276 {
277 case REMOTE_NDIS_PACKET_MSG:
278 DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, data offset %u data len %u, # oob %u, oob offset %u, oob len %u, pkt offset %u, pkt len %u",
279 RndisMessage->MessageLength,
280 RndisMessage->Message.Packet.DataOffset,
281 RndisMessage->Message.Packet.DataLength,
282 RndisMessage->Message.Packet.NumOOBDataElements,
283 RndisMessage->Message.Packet.OOBDataOffset,
284 RndisMessage->Message.Packet.OOBDataLength,
285 RndisMessage->Message.Packet.PerPacketInfoOffset,
286 RndisMessage->Message.Packet.PerPacketInfoLength);
287 break;
288
289 case REMOTE_NDIS_INITIALIZE_CMPLT:
290 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT (len %u, id 0x%x, status 0x%x, major %d, minor %d, device flags %d, max xfer size 0x%x, max pkts %u, pkt aligned %u)",
291 RndisMessage->MessageLength,
292 RndisMessage->Message.InitializeComplete.RequestId,
293 RndisMessage->Message.InitializeComplete.Status,
294 RndisMessage->Message.InitializeComplete.MajorVersion,
295 RndisMessage->Message.InitializeComplete.MinorVersion,
296 RndisMessage->Message.InitializeComplete.DeviceFlags,
297 RndisMessage->Message.InitializeComplete.MaxTransferSize,
298 RndisMessage->Message.InitializeComplete.MaxPacketsPerMessage,
299 RndisMessage->Message.InitializeComplete.PacketAlignmentFactor);
300 break;
301
302 case REMOTE_NDIS_QUERY_CMPLT:
303 DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT (len %u, id 0x%x, status 0x%x, buf len %u, buf offset %u)",
304 RndisMessage->MessageLength,
305 RndisMessage->Message.QueryComplete.RequestId,
306 RndisMessage->Message.QueryComplete.Status,
307 RndisMessage->Message.QueryComplete.InformationBufferLength,
308 RndisMessage->Message.QueryComplete.InformationBufferOffset);
309 break;
310
311 case REMOTE_NDIS_SET_CMPLT:
312 DPRINT_DBG(NETVSC, "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
313 RndisMessage->MessageLength,
314 RndisMessage->Message.SetComplete.RequestId,
315 RndisMessage->Message.SetComplete.Status);
316 break;
317
318 case REMOTE_NDIS_INDICATE_STATUS_MSG:
319 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG (len %u, status 0x%x, buf len %u, buf offset %u)",
320 RndisMessage->MessageLength,
321 RndisMessage->Message.IndicateStatus.Status,
322 RndisMessage->Message.IndicateStatus.StatusBufferLength,
323 RndisMessage->Message.IndicateStatus.StatusBufferOffset);
324 break;
325
326 default:
327 DPRINT_DBG(NETVSC, "0x%x (len %u)",
328 RndisMessage->NdisMessageType,
329 RndisMessage->MessageLength);
330 break;
331 }
332}
333
334static int
335RndisFilterSendRequest(
336 RNDIS_DEVICE *Device,
337 RNDIS_REQUEST *Request
338 )
339{
340 int ret=0;
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200341 struct hv_netvsc_packet *packet;
Hank Janssenfceaf242009-07-13 15:34:54 -0700342
343 DPRINT_ENTER(NETVSC);
344
Bill Pemberton454f18a2009-07-27 16:47:24 -0400345 /* Setup the packet to send it */
Hank Janssenfceaf242009-07-13 15:34:54 -0700346 packet = &Request->Packet;
347
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700348 packet->IsDataPacket = false;
Hank Janssenfceaf242009-07-13 15:34:54 -0700349 packet->TotalDataBufferLength = Request->RequestMessage.MessageLength;
350 packet->PageBufferCount = 1;
351
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -0700352 packet->PageBuffers[0].Pfn = virt_to_phys(&Request->RequestMessage) >> PAGE_SHIFT;
Hank Janssenfceaf242009-07-13 15:34:54 -0700353 packet->PageBuffers[0].Length = Request->RequestMessage.MessageLength;
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700354 packet->PageBuffers[0].Offset = (unsigned long)&Request->RequestMessage & (PAGE_SIZE -1);
Hank Janssenfceaf242009-07-13 15:34:54 -0700355
Bill Pemberton454f18a2009-07-27 16:47:24 -0400356 packet->Completion.Send.SendCompletionContext = Request;/* packet; */
Hank Janssenfceaf242009-07-13 15:34:54 -0700357 packet->Completion.Send.OnSendCompletion = RndisFilterOnSendRequestCompletion;
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700358 packet->Completion.Send.SendCompletionTid = (unsigned long)Device;
Hank Janssenfceaf242009-07-13 15:34:54 -0700359
360 ret = gRndisFilter.InnerDriver.OnSend(Device->NetDevice->Device, packet);
361 DPRINT_EXIT(NETVSC);
362 return ret;
363}
364
365
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700366static void RndisFilterReceiveResponse(RNDIS_DEVICE *Device,
367 struct rndis_message *Response)
Hank Janssenfceaf242009-07-13 15:34:54 -0700368{
369 LIST_ENTRY *anchor;
370 LIST_ENTRY *curr;
371 RNDIS_REQUEST *request=NULL;
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700372 bool found = false;
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700373 unsigned long flags;
Hank Janssenfceaf242009-07-13 15:34:54 -0700374
375 DPRINT_ENTER(NETVSC);
376
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700377 spin_lock_irqsave(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700378 ITERATE_LIST_ENTRIES(anchor, curr, &Device->RequestList)
379 {
380 request = CONTAINING_RECORD(curr, RNDIS_REQUEST, ListEntry);
381
Bill Pemberton454f18a2009-07-27 16:47:24 -0400382 /* All request/response message contains RequestId as the 1st field */
Hank Janssenfceaf242009-07-13 15:34:54 -0700383 if (request->RequestMessage.Message.InitializeRequest.RequestId == Response->Message.InitializeComplete.RequestId)
384 {
385 DPRINT_DBG(NETVSC, "found rndis request for this response (id 0x%x req type 0x%x res type 0x%x)",
386 request->RequestMessage.Message.InitializeRequest.RequestId, request->RequestMessage.NdisMessageType, Response->NdisMessageType);
387
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700388 found = true;
Hank Janssenfceaf242009-07-13 15:34:54 -0700389 break;
390 }
391 }
Greg Kroah-Hartman880fb892009-07-15 14:55:29 -0700392 spin_unlock_irqrestore(&Device->request_lock, flags);
Hank Janssenfceaf242009-07-13 15:34:54 -0700393
394 if (found)
395 {
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700396 if (Response->MessageLength <= sizeof(struct rndis_message))
Hank Janssenfceaf242009-07-13 15:34:54 -0700397 {
398 memcpy(&request->ResponseMessage, Response, Response->MessageLength);
399 }
400 else
401 {
Greg Kroah-Hartmanb7d7ae62009-07-28 16:18:05 -0700402 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 -0700403
Bill Pemberton454f18a2009-07-27 16:47:24 -0400404 if (Response->NdisMessageType == REMOTE_NDIS_RESET_CMPLT) /* does not have a request id field */
Hank Janssenfceaf242009-07-13 15:34:54 -0700405 {
406 request->ResponseMessage.Message.ResetComplete.Status = STATUS_BUFFER_OVERFLOW;
407 }
408 else
409 {
410 request->ResponseMessage.Message.InitializeComplete.Status = STATUS_BUFFER_OVERFLOW;
411 }
412 }
413
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700414 osd_WaitEventSet(request->WaitEvent);
Hank Janssenfceaf242009-07-13 15:34:54 -0700415 }
416 else
417 {
418 DPRINT_ERR(NETVSC, "no rndis request found for this response (id 0x%x res type 0x%x)",
419 Response->Message.InitializeComplete.RequestId, Response->NdisMessageType);
420 }
421
422 DPRINT_EXIT(NETVSC);
423}
424
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700425static void RndisFilterReceiveIndicateStatus(RNDIS_DEVICE *Device,
426 struct rndis_message *Response)
Hank Janssenfceaf242009-07-13 15:34:54 -0700427{
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700428 struct rndis_indicate_status *indicate = &Response->Message.IndicateStatus;
Hank Janssenfceaf242009-07-13 15:34:54 -0700429
430 if (indicate->Status == RNDIS_STATUS_MEDIA_CONNECT)
431 {
432 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 1);
433 }
434 else if (indicate->Status == RNDIS_STATUS_MEDIA_DISCONNECT)
435 {
436 gRndisFilter.InnerDriver.OnLinkStatusChanged(Device->NetDevice->Device, 0);
437 }
438 else
439 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400440 /* TODO: */
Hank Janssenfceaf242009-07-13 15:34:54 -0700441 }
442}
443
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700444static void RndisFilterReceiveData(RNDIS_DEVICE *Device,
445 struct rndis_message *Message,
446 struct hv_netvsc_packet *Packet)
Hank Janssenfceaf242009-07-13 15:34:54 -0700447{
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700448 struct rndis_packet *rndisPacket;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700449 u32 dataOffset;
Hank Janssenfceaf242009-07-13 15:34:54 -0700450
451 DPRINT_ENTER(NETVSC);
452
Bill Pemberton454f18a2009-07-27 16:47:24 -0400453 /* empty ethernet frame ?? */
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700454 ASSERT(Packet->PageBuffers[0].Length > RNDIS_MESSAGE_SIZE(struct rndis_packet));
Hank Janssenfceaf242009-07-13 15:34:54 -0700455
456 rndisPacket = &Message->Message.Packet;
457
Bill Pemberton454f18a2009-07-27 16:47:24 -0400458 /* FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this */
459 /* netvsc packet (ie TotalDataBufferLength != MessageLength) */
Hank Janssenfceaf242009-07-13 15:34:54 -0700460
Bill Pemberton454f18a2009-07-27 16:47:24 -0400461 /* Remove the rndis header and pass it back up the stack */
Hank Janssenfceaf242009-07-13 15:34:54 -0700462 dataOffset = RNDIS_HEADER_SIZE + rndisPacket->DataOffset;
463
464 Packet->TotalDataBufferLength -= dataOffset;
465 Packet->PageBuffers[0].Offset += dataOffset;
466 Packet->PageBuffers[0].Length -= dataOffset;
467
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -0700468 Packet->IsDataPacket = true;
Hank Janssenfceaf242009-07-13 15:34:54 -0700469
470 gRndisFilter.InnerDriver.OnReceiveCallback(Device->NetDevice->Device, Packet);
471
472 DPRINT_EXIT(NETVSC);
473}
474
475static int
476RndisFilterOnReceive(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200477 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +0200478 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -0700479 )
480{
Bill Pembertond1af1db72009-07-27 16:47:44 -0400481 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -0700482 RNDIS_DEVICE *rndisDevice;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700483 struct rndis_message rndisMessage;
484 struct rndis_message *rndisHeader;
Hank Janssenfceaf242009-07-13 15:34:54 -0700485
486 DPRINT_ENTER(NETVSC);
487
488 ASSERT(netDevice);
Bill Pemberton454f18a2009-07-27 16:47:24 -0400489 /* Make sure the rndis device state is initialized */
Hank Janssenfceaf242009-07-13 15:34:54 -0700490 if (!netDevice->Extension)
491 {
492 DPRINT_ERR(NETVSC, "got rndis message but no rndis device...dropping this message!");
493 DPRINT_EXIT(NETVSC);
494 return -1;
495 }
496
497 rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
498 if (rndisDevice->State == RNDIS_DEV_UNINITIALIZED)
499 {
500 DPRINT_ERR(NETVSC, "got rndis message but rndis device uninitialized...dropping this message!");
501 DPRINT_EXIT(NETVSC);
502 return -1;
503 }
504
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700505 rndisHeader = (struct rndis_message *)kmap_atomic(pfn_to_page(Packet->PageBuffers[0].Pfn), KM_IRQ0);
Hank Janssenfceaf242009-07-13 15:34:54 -0700506
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700507 rndisHeader = (void*)((unsigned long)rndisHeader + Packet->PageBuffers[0].Offset);
Hank Janssenfceaf242009-07-13 15:34:54 -0700508
Bill Pemberton454f18a2009-07-27 16:47:24 -0400509 /* Make sure we got a valid rndis message */
510 /* FIXME: There seems to be a bug in set completion msg where its MessageLength is 16 bytes but */
511 /* the ByteCount field in the xfer page range shows 52 bytes */
Hank Janssenfceaf242009-07-13 15:34:54 -0700512#if 0
513 if ( Packet->TotalDataBufferLength != rndisHeader->MessageLength )
514 {
Bill Pemberton45da89e2009-07-29 17:00:15 -0400515 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
Hank Janssenfceaf242009-07-13 15:34:54 -0700516
517 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u bytes got %u)...dropping this message!",
518 rndisHeader->MessageLength, Packet->TotalDataBufferLength);
519 DPRINT_EXIT(NETVSC);
520 return -1;
521 }
522#endif
523
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700524 if ((rndisHeader->NdisMessageType != REMOTE_NDIS_PACKET_MSG) && (rndisHeader->MessageLength > sizeof(struct rndis_message)))
Hank Janssenfceaf242009-07-13 15:34:54 -0700525 {
Greg Kroah-Hartmanb7d7ae62009-07-28 16:18:05 -0700526 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow detected (got %u, max %zu)...marking it an error!",
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700527 rndisHeader->MessageLength, sizeof(struct rndis_message));
Hank Janssenfceaf242009-07-13 15:34:54 -0700528 }
529
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700530 memcpy(&rndisMessage, rndisHeader, (rndisHeader->MessageLength > sizeof(struct rndis_message))?sizeof(struct rndis_message):rndisHeader->MessageLength);
Hank Janssenfceaf242009-07-13 15:34:54 -0700531
Bill Pemberton45da89e2009-07-29 17:00:15 -0400532 kunmap_atomic(rndisHeader - Packet->PageBuffers[0].Offset, KM_IRQ0);
Hank Janssenfceaf242009-07-13 15:34:54 -0700533
534 DumpRndisMessage(&rndisMessage);
535
536 switch (rndisMessage.NdisMessageType)
537 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400538 /* data msg */
Hank Janssenfceaf242009-07-13 15:34:54 -0700539 case REMOTE_NDIS_PACKET_MSG:
540 RndisFilterReceiveData(rndisDevice, &rndisMessage, Packet);
541 break;
542
Bill Pemberton454f18a2009-07-27 16:47:24 -0400543 /* completion msgs */
Hank Janssenfceaf242009-07-13 15:34:54 -0700544 case REMOTE_NDIS_INITIALIZE_CMPLT:
545 case REMOTE_NDIS_QUERY_CMPLT:
546 case REMOTE_NDIS_SET_CMPLT:
Bill Pemberton454f18a2009-07-27 16:47:24 -0400547 /* case REMOTE_NDIS_RESET_CMPLT: */
548 /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
Hank Janssenfceaf242009-07-13 15:34:54 -0700549 RndisFilterReceiveResponse(rndisDevice, &rndisMessage);
550 break;
551
Bill Pemberton454f18a2009-07-27 16:47:24 -0400552 /* notification msgs */
Hank Janssenfceaf242009-07-13 15:34:54 -0700553 case REMOTE_NDIS_INDICATE_STATUS_MSG:
554 RndisFilterReceiveIndicateStatus(rndisDevice, &rndisMessage);
555 break;
556 default:
557 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)", rndisMessage.NdisMessageType, rndisMessage.MessageLength);
558 break;
559 }
560
561 DPRINT_EXIT(NETVSC);
562 return 0;
563}
564
565
566static int
567RndisFilterQueryDevice(
568 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700569 u32 Oid,
Greg Kroah-Hartmane20f6832009-07-14 15:07:21 -0700570 void *Result,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700571 u32 *ResultSize
Hank Janssenfceaf242009-07-13 15:34:54 -0700572 )
573{
574 RNDIS_REQUEST *request;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700575 u32 inresultSize = *ResultSize;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700576 struct rndis_query_request *query;
577 struct rndis_query_complete *queryComplete;
Hank Janssenfceaf242009-07-13 15:34:54 -0700578 int ret=0;
579
580 DPRINT_ENTER(NETVSC);
581
582 ASSERT(Result);
583
584 *ResultSize = 0;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700585 request = GetRndisRequest(Device, REMOTE_NDIS_QUERY_MSG, RNDIS_MESSAGE_SIZE(struct rndis_query_request));
Hank Janssenfceaf242009-07-13 15:34:54 -0700586 if (!request)
587 {
588 ret = -1;
589 goto Cleanup;
590 }
591
Bill Pemberton454f18a2009-07-27 16:47:24 -0400592 /* Setup the rndis query */
Hank Janssenfceaf242009-07-13 15:34:54 -0700593 query = &request->RequestMessage.Message.QueryRequest;
594 query->Oid = Oid;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700595 query->InformationBufferOffset = sizeof(struct rndis_query_request);
Hank Janssenfceaf242009-07-13 15:34:54 -0700596 query->InformationBufferLength = 0;
597 query->DeviceVcHandle = 0;
598
599 ret = RndisFilterSendRequest(Device, request);
600 if (ret != 0)
601 {
602 goto Cleanup;
603 }
604
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700605 osd_WaitEventWait(request->WaitEvent);
Hank Janssenfceaf242009-07-13 15:34:54 -0700606
Bill Pemberton454f18a2009-07-27 16:47:24 -0400607 /* Copy the response back */
Hank Janssenfceaf242009-07-13 15:34:54 -0700608 queryComplete = &request->ResponseMessage.Message.QueryComplete;
609
610 if (queryComplete->InformationBufferLength > inresultSize)
611 {
612 ret = -1;
613 goto Cleanup;
614 }
615
616 memcpy(Result,
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700617 (void*)((unsigned long)queryComplete + queryComplete->InformationBufferOffset),
Hank Janssenfceaf242009-07-13 15:34:54 -0700618 queryComplete->InformationBufferLength);
619
620 *ResultSize = queryComplete->InformationBufferLength;
621
622Cleanup:
623 if (request)
624 {
625 PutRndisRequest(Device, request);
626 }
627 DPRINT_EXIT(NETVSC);
628
629 return ret;
630}
631
632static inline int
633RndisFilterQueryDeviceMac(
634 RNDIS_DEVICE *Device
635 )
636{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700637 u32 size=HW_MACADDR_LEN;
Hank Janssenfceaf242009-07-13 15:34:54 -0700638
639 return RndisFilterQueryDevice(Device,
640 RNDIS_OID_802_3_PERMANENT_ADDRESS,
641 Device->HwMacAddr,
642 &size);
643}
644
645static inline int
646RndisFilterQueryDeviceLinkStatus(
647 RNDIS_DEVICE *Device
648 )
649{
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700650 u32 size=sizeof(u32);
Hank Janssenfceaf242009-07-13 15:34:54 -0700651
652 return RndisFilterQueryDevice(Device,
653 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
654 &Device->LinkStatus,
655 &size);
656}
657
658static int
659RndisFilterSetPacketFilter(
660 RNDIS_DEVICE *Device,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700661 u32 NewFilter
Hank Janssenfceaf242009-07-13 15:34:54 -0700662 )
663{
664 RNDIS_REQUEST *request;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700665 struct rndis_set_request *set;
666 struct rndis_set_complete *setComplete;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700667 u32 status;
Hank Janssenfceaf242009-07-13 15:34:54 -0700668 int ret;
669
670 DPRINT_ENTER(NETVSC);
671
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700672 ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= sizeof(struct rndis_message));
Hank Janssenfceaf242009-07-13 15:34:54 -0700673
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700674 request = GetRndisRequest(Device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32));
Hank Janssenfceaf242009-07-13 15:34:54 -0700675 if (!request)
676 {
677 ret = -1;
678 goto Cleanup;
679 }
680
Bill Pemberton454f18a2009-07-27 16:47:24 -0400681 /* Setup the rndis set */
Hank Janssenfceaf242009-07-13 15:34:54 -0700682 set = &request->RequestMessage.Message.SetRequest;
683 set->Oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700684 set->InformationBufferLength = sizeof(u32);
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700685 set->InformationBufferOffset = sizeof(struct rndis_set_request);
Hank Janssenfceaf242009-07-13 15:34:54 -0700686
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700687 memcpy((void*)(unsigned long)set + sizeof(struct rndis_set_request), &NewFilter, sizeof(u32));
Hank Janssenfceaf242009-07-13 15:34:54 -0700688
689 ret = RndisFilterSendRequest(Device, request);
690 if (ret != 0)
691 {
692 goto Cleanup;
693 }
694
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700695 ret = osd_WaitEventWaitEx(request->WaitEvent, 2000/*2sec*/);
Hank Janssenfceaf242009-07-13 15:34:54 -0700696 if (!ret)
697 {
698 ret = -1;
699 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
Bill Pemberton454f18a2009-07-27 16:47:24 -0400700 /* We cant deallocate the request since we may still receive a send completion for it. */
Hank Janssenfceaf242009-07-13 15:34:54 -0700701 goto Exit;
702 }
703 else
704 {
705 if (ret > 0)
706 {
707 ret = 0;
708 }
709 setComplete = &request->ResponseMessage.Message.SetComplete;
710 status = setComplete->Status;
711 }
712
713Cleanup:
714 if (request)
715 {
716 PutRndisRequest(Device, request);
717 }
718Exit:
719 DPRINT_EXIT(NETVSC);
720
721 return ret;
722}
723
Greg Kroah-Hartman7e23a6e2009-08-27 15:58:15 -0700724int RndisFilterInit(struct netvsc_driver *Driver)
Hank Janssenfceaf242009-07-13 15:34:54 -0700725{
726 DPRINT_ENTER(NETVSC);
727
Greg Kroah-Hartmanb7d7ae62009-07-28 16:18:05 -0700728 DPRINT_DBG(NETVSC, "sizeof(RNDIS_FILTER_PACKET) == %zd", sizeof(RNDIS_FILTER_PACKET));
Hank Janssenfceaf242009-07-13 15:34:54 -0700729
730 Driver->RequestExtSize = sizeof(RNDIS_FILTER_PACKET);
Bill Pemberton454f18a2009-07-27 16:47:24 -0400731 Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
Hank Janssenfceaf242009-07-13 15:34:54 -0700732
Bill Pemberton454f18a2009-07-27 16:47:24 -0400733 /* Driver->Context = rndisDriver; */
Hank Janssenfceaf242009-07-13 15:34:54 -0700734
735 memset(&gRndisFilter, 0, sizeof(RNDIS_FILTER_DRIVER_OBJECT));
736
737 /*rndisDriver->Driver = Driver;
738
739 ASSERT(Driver->OnLinkStatusChanged);
740 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
741
Bill Pemberton454f18a2009-07-27 16:47:24 -0400742 /* Save the original dispatch handlers before we override it */
Hank Janssenfceaf242009-07-13 15:34:54 -0700743 gRndisFilter.InnerDriver.Base.OnDeviceAdd = Driver->Base.OnDeviceAdd;
744 gRndisFilter.InnerDriver.Base.OnDeviceRemove = Driver->Base.OnDeviceRemove;
745 gRndisFilter.InnerDriver.Base.OnCleanup = Driver->Base.OnCleanup;
746
747 ASSERT(Driver->OnSend);
748 ASSERT(Driver->OnReceiveCallback);
749 gRndisFilter.InnerDriver.OnSend = Driver->OnSend;
750 gRndisFilter.InnerDriver.OnReceiveCallback = Driver->OnReceiveCallback;
751 gRndisFilter.InnerDriver.OnLinkStatusChanged = Driver->OnLinkStatusChanged;
752
Bill Pemberton454f18a2009-07-27 16:47:24 -0400753 /* Override */
Hank Janssenfceaf242009-07-13 15:34:54 -0700754 Driver->Base.OnDeviceAdd = RndisFilterOnDeviceAdd;
755 Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
756 Driver->Base.OnCleanup = RndisFilterOnCleanup;
757 Driver->OnSend = RndisFilterOnSend;
758 Driver->OnOpen = RndisFilterOnOpen;
759 Driver->OnClose = RndisFilterOnClose;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400760 /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
Hank Janssenfceaf242009-07-13 15:34:54 -0700761 Driver->OnReceiveCallback = RndisFilterOnReceive;
762
763 DPRINT_EXIT(NETVSC);
764
765 return 0;
766}
767
768static int
769RndisFilterInitDevice(
770 RNDIS_DEVICE *Device
771 )
772{
773 RNDIS_REQUEST *request;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700774 struct rndis_initialize_request *init;
775 struct rndis_initialize_complete *initComplete;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700776 u32 status;
Hank Janssenfceaf242009-07-13 15:34:54 -0700777 int ret;
778
779 DPRINT_ENTER(NETVSC);
780
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700781 request = GetRndisRequest(Device, REMOTE_NDIS_INITIALIZE_MSG, RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
Hank Janssenfceaf242009-07-13 15:34:54 -0700782 if (!request)
783 {
784 ret = -1;
785 goto Cleanup;
786 }
787
Bill Pemberton454f18a2009-07-27 16:47:24 -0400788 /* Setup the rndis set */
Hank Janssenfceaf242009-07-13 15:34:54 -0700789 init = &request->RequestMessage.Message.InitializeRequest;
790 init->MajorVersion = RNDIS_MAJOR_VERSION;
791 init->MinorVersion = RNDIS_MINOR_VERSION;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400792 init->MaxTransferSize = 2048; /* FIXME: Use 1536 - rounded ethernet frame size */
Hank Janssenfceaf242009-07-13 15:34:54 -0700793
794 Device->State = RNDIS_DEV_INITIALIZING;
795
796 ret = RndisFilterSendRequest(Device, request);
797 if (ret != 0)
798 {
799 Device->State = RNDIS_DEV_UNINITIALIZED;
800 goto Cleanup;
801 }
802
Greg Kroah-Hartmanbfc30aa2009-07-29 15:40:18 -0700803 osd_WaitEventWait(request->WaitEvent);
Hank Janssenfceaf242009-07-13 15:34:54 -0700804
805 initComplete = &request->ResponseMessage.Message.InitializeComplete;
806 status = initComplete->Status;
807 if (status == RNDIS_STATUS_SUCCESS)
808 {
809 Device->State = RNDIS_DEV_INITIALIZED;
810 ret = 0;
811 }
812 else
813 {
814 Device->State = RNDIS_DEV_UNINITIALIZED;
815 ret = -1;
816 }
817
818Cleanup:
819 if (request)
820 {
821 PutRndisRequest(Device, request);
822 }
823 DPRINT_EXIT(NETVSC);
824
825 return ret;
826}
827
828static void
829RndisFilterHaltDevice(
830 RNDIS_DEVICE *Device
831 )
832{
833 RNDIS_REQUEST *request;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700834 struct rndis_halt_request *halt;
Hank Janssenfceaf242009-07-13 15:34:54 -0700835
836 DPRINT_ENTER(NETVSC);
837
Bill Pemberton454f18a2009-07-27 16:47:24 -0400838 /* Attempt to do a rndis device halt */
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -0700839 request = GetRndisRequest(Device, REMOTE_NDIS_HALT_MSG, RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
Hank Janssenfceaf242009-07-13 15:34:54 -0700840 if (!request)
841 {
842 goto Cleanup;
843 }
844
Bill Pemberton454f18a2009-07-27 16:47:24 -0400845 /* Setup the rndis set */
Hank Janssenfceaf242009-07-13 15:34:54 -0700846 halt = &request->RequestMessage.Message.HaltRequest;
Bill Pembertonf4888412009-07-29 17:00:12 -0400847 halt->RequestId = atomic_inc_return(&Device->NewRequestId);
Hank Janssenfceaf242009-07-13 15:34:54 -0700848
Bill Pemberton454f18a2009-07-27 16:47:24 -0400849 /* Ignore return since this msg is optional. */
Hank Janssenfceaf242009-07-13 15:34:54 -0700850 RndisFilterSendRequest(Device, request);
851
852 Device->State = RNDIS_DEV_UNINITIALIZED;
853
854Cleanup:
855 if (request)
856 {
857 PutRndisRequest(Device, request);
858 }
859 DPRINT_EXIT(NETVSC);
860 return;
861}
862
863
864static int
865RndisFilterOpenDevice(
866 RNDIS_DEVICE *Device
867 )
868{
869 int ret=0;
870
871 DPRINT_ENTER(NETVSC);
872
873 if (Device->State != RNDIS_DEV_INITIALIZED)
874 return 0;
875
876 ret = RndisFilterSetPacketFilter(Device, NDIS_PACKET_TYPE_BROADCAST|NDIS_PACKET_TYPE_DIRECTED);
877 if (ret == 0)
878 {
879 Device->State = RNDIS_DEV_DATAINITIALIZED;
880 }
881
882 DPRINT_EXIT(NETVSC);
883 return ret;
884}
885
886static int
887RndisFilterCloseDevice(
888 RNDIS_DEVICE *Device
889 )
890{
891 int ret;
892
893 DPRINT_ENTER(NETVSC);
894
895 if (Device->State != RNDIS_DEV_DATAINITIALIZED)
896 return 0;
897
898 ret = RndisFilterSetPacketFilter(Device, 0);
899 if (ret == 0)
900 {
901 Device->State = RNDIS_DEV_INITIALIZED;
902 }
903
904 DPRINT_EXIT(NETVSC);
905
906 return ret;
907}
908
909
Greg Kroah-Hartmanbd1de702009-07-29 09:04:51 -0700910static int
Hank Janssenfceaf242009-07-13 15:34:54 -0700911RndisFilterOnDeviceAdd(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200912 struct hv_device *Device,
Hank Janssenfceaf242009-07-13 15:34:54 -0700913 void *AdditionalInfo
914 )
915{
916 int ret;
Bill Pembertond1af1db72009-07-27 16:47:44 -0400917 struct NETVSC_DEVICE *netDevice;
Hank Janssenfceaf242009-07-13 15:34:54 -0700918 RNDIS_DEVICE *rndisDevice;
Greg Kroah-Hartman7e23a6e2009-08-27 15:58:15 -0700919 struct netvsc_device_info *deviceInfo = (struct netvsc_device_info *)AdditionalInfo;
Hank Janssenfceaf242009-07-13 15:34:54 -0700920
921 DPRINT_ENTER(NETVSC);
922
Hank Janssenfceaf242009-07-13 15:34:54 -0700923 rndisDevice = GetRndisDevice();
924 if (!rndisDevice)
925 {
926 DPRINT_EXIT(NETVSC);
927 return -1;
928 }
929
930 DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
931
Bill Pemberton454f18a2009-07-27 16:47:24 -0400932 /* Let the inner driver handle this first to create the netvsc channel */
933 /* NOTE! Once the channel is created, we may get a receive callback */
934 /* (RndisFilterOnReceive()) before this call is completed */
Hank Janssenfceaf242009-07-13 15:34:54 -0700935 ret = gRndisFilter.InnerDriver.Base.OnDeviceAdd(Device, AdditionalInfo);
936 if (ret != 0)
937 {
938 PutRndisDevice(rndisDevice);
939 DPRINT_EXIT(NETVSC);
940 return ret;
941 }
942
Bill Pemberton454f18a2009-07-27 16:47:24 -0400943
944 /* Initialize the rndis device */
945
Bill Pembertond1af1db72009-07-27 16:47:44 -0400946 netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -0700947 ASSERT(netDevice);
948 ASSERT(netDevice->Device);
949
950 netDevice->Extension = rndisDevice;
951 rndisDevice->NetDevice = netDevice;
952
Bill Pemberton454f18a2009-07-27 16:47:24 -0400953 /* Send the rndis initialization message */
Hank Janssenfceaf242009-07-13 15:34:54 -0700954 ret = RndisFilterInitDevice(rndisDevice);
955 if (ret != 0)
956 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400957 /* TODO: If rndis init failed, we will need to shut down the channel */
Hank Janssenfceaf242009-07-13 15:34:54 -0700958 }
959
Bill Pemberton454f18a2009-07-27 16:47:24 -0400960 /* Get the mac address */
Hank Janssenfceaf242009-07-13 15:34:54 -0700961 ret = RndisFilterQueryDeviceMac(rndisDevice);
962 if (ret != 0)
963 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400964 /* TODO: shutdown rndis device and the channel */
Hank Janssenfceaf242009-07-13 15:34:54 -0700965 }
966
967 DPRINT_INFO(NETVSC, "Device 0x%p mac addr %02x%02x%02x%02x%02x%02x",
968 rndisDevice,
969 rndisDevice->HwMacAddr[0],
970 rndisDevice->HwMacAddr[1],
971 rndisDevice->HwMacAddr[2],
972 rndisDevice->HwMacAddr[3],
973 rndisDevice->HwMacAddr[4],
974 rndisDevice->HwMacAddr[5]);
975
976 memcpy(deviceInfo->MacAddr, rndisDevice->HwMacAddr, HW_MACADDR_LEN);
977
978 RndisFilterQueryDeviceLinkStatus(rndisDevice);
979
980 deviceInfo->LinkState = rndisDevice->LinkStatus;
981 DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice, ((deviceInfo->LinkState)?("down"):("up")));
982
983 DPRINT_EXIT(NETVSC);
984
985 return ret;
986}
987
988
989static int
990RndisFilterOnDeviceRemove(
Nicolas Palix3d3b5512009-07-28 17:32:53 +0200991 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -0700992 )
993{
Bill Pembertond1af1db72009-07-27 16:47:44 -0400994 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -0700995 RNDIS_DEVICE *rndisDevice = (RNDIS_DEVICE*)netDevice->Extension;
996
997 DPRINT_ENTER(NETVSC);
998
Bill Pemberton454f18a2009-07-27 16:47:24 -0400999 /* Halt and release the rndis device */
Hank Janssenfceaf242009-07-13 15:34:54 -07001000 RndisFilterHaltDevice(rndisDevice);
1001
1002 PutRndisDevice(rndisDevice);
1003 netDevice->Extension = NULL;
1004
Bill Pemberton454f18a2009-07-27 16:47:24 -04001005 /* Pass control to inner driver to remove the device */
Hank Janssenfceaf242009-07-13 15:34:54 -07001006 gRndisFilter.InnerDriver.Base.OnDeviceRemove(Device);
1007
1008 DPRINT_EXIT(NETVSC);
1009
1010 return 0;
1011}
1012
1013
1014static void
1015RndisFilterOnCleanup(
Nicolas Palix775ef252009-07-29 14:09:45 +02001016 struct hv_driver *Driver
Hank Janssenfceaf242009-07-13 15:34:54 -07001017 )
1018{
1019 DPRINT_ENTER(NETVSC);
1020
1021 DPRINT_EXIT(NETVSC);
1022}
1023
1024static int
1025RndisFilterOnOpen(
Nicolas Palix3d3b5512009-07-28 17:32:53 +02001026 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -07001027 )
1028{
1029 int ret;
Bill Pembertond1af1db72009-07-27 16:47:44 -04001030 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -07001031
1032 DPRINT_ENTER(NETVSC);
1033
1034 ASSERT(netDevice);
1035 ret = RndisFilterOpenDevice((RNDIS_DEVICE*)netDevice->Extension);
1036
1037 DPRINT_EXIT(NETVSC);
1038
1039 return ret;
1040}
1041
1042static int
1043RndisFilterOnClose(
Nicolas Palix3d3b5512009-07-28 17:32:53 +02001044 struct hv_device *Device
Hank Janssenfceaf242009-07-13 15:34:54 -07001045 )
1046{
1047 int ret;
Bill Pembertond1af1db72009-07-27 16:47:44 -04001048 struct NETVSC_DEVICE *netDevice = (struct NETVSC_DEVICE*)Device->Extension;
Hank Janssenfceaf242009-07-13 15:34:54 -07001049
1050 DPRINT_ENTER(NETVSC);
1051
1052 ASSERT(netDevice);
1053 ret = RndisFilterCloseDevice((RNDIS_DEVICE*)netDevice->Extension);
1054
1055 DPRINT_EXIT(NETVSC);
1056
1057 return ret;
1058}
1059
1060
1061static int
1062RndisFilterOnSend(
Nicolas Palix3d3b5512009-07-28 17:32:53 +02001063 struct hv_device *Device,
Nicolas Palix4193d4f2009-07-29 14:10:10 +02001064 struct hv_netvsc_packet *Packet
Hank Janssenfceaf242009-07-13 15:34:54 -07001065 )
1066{
1067 int ret=0;
1068 RNDIS_FILTER_PACKET *filterPacket;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -07001069 struct rndis_message *rndisMessage;
1070 struct rndis_packet *rndisPacket;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -07001071 u32 rndisMessageSize;
Hank Janssenfceaf242009-07-13 15:34:54 -07001072
1073 DPRINT_ENTER(NETVSC);
1074
Bill Pemberton454f18a2009-07-27 16:47:24 -04001075 /* Add the rndis header */
Hank Janssenfceaf242009-07-13 15:34:54 -07001076 filterPacket = (RNDIS_FILTER_PACKET*)Packet->Extension;
1077 ASSERT(filterPacket);
1078
1079 memset(filterPacket, 0, sizeof(RNDIS_FILTER_PACKET));
1080
1081 rndisMessage = &filterPacket->Message;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -07001082 rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
Hank Janssenfceaf242009-07-13 15:34:54 -07001083
1084 rndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
1085 rndisMessage->MessageLength = Packet->TotalDataBufferLength + rndisMessageSize;
1086
1087 rndisPacket = &rndisMessage->Message.Packet;
Greg Kroah-Hartman9f33d052009-08-19 16:26:24 -07001088 rndisPacket->DataOffset = sizeof(struct rndis_packet);
Hank Janssenfceaf242009-07-13 15:34:54 -07001089 rndisPacket->DataLength = Packet->TotalDataBufferLength;
1090
Greg Kroah-Hartman0e727612009-07-15 12:46:44 -07001091 Packet->IsDataPacket = true;
Greg Kroah-Hartmanfa56d362009-07-29 15:39:27 -07001092 Packet->PageBuffers[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -07001093 Packet->PageBuffers[0].Offset = (unsigned long)rndisMessage & (PAGE_SIZE-1);
Hank Janssenfceaf242009-07-13 15:34:54 -07001094 Packet->PageBuffers[0].Length = rndisMessageSize;
1095
Bill Pemberton454f18a2009-07-27 16:47:24 -04001096 /* Save the packet send completion and context */
Hank Janssenfceaf242009-07-13 15:34:54 -07001097 filterPacket->OnCompletion = Packet->Completion.Send.OnSendCompletion;
1098 filterPacket->CompletionContext = Packet->Completion.Send.SendCompletionContext;
1099
Bill Pemberton454f18a2009-07-27 16:47:24 -04001100 /* Use ours */
Hank Janssenfceaf242009-07-13 15:34:54 -07001101 Packet->Completion.Send.OnSendCompletion = RndisFilterOnSendCompletion;
1102 Packet->Completion.Send.SendCompletionContext = filterPacket;
1103
1104 ret = gRndisFilter.InnerDriver.OnSend(Device, Packet);
1105 if (ret != 0)
1106 {
Bill Pemberton454f18a2009-07-27 16:47:24 -04001107 /* Reset the completion to originals to allow retries from above */
Hank Janssenfceaf242009-07-13 15:34:54 -07001108 Packet->Completion.Send.OnSendCompletion = filterPacket->OnCompletion;
1109 Packet->Completion.Send.SendCompletionContext = filterPacket->CompletionContext;
1110 }
1111
1112 DPRINT_EXIT(NETVSC);
1113
1114 return ret;
1115}
1116
1117static void
1118RndisFilterOnSendCompletion(
1119 void *Context)
1120{
1121 RNDIS_FILTER_PACKET *filterPacket = (RNDIS_FILTER_PACKET *)Context;
1122
1123 DPRINT_ENTER(NETVSC);
1124
Bill Pemberton454f18a2009-07-27 16:47:24 -04001125 /* Pass it back to the original handler */
Hank Janssenfceaf242009-07-13 15:34:54 -07001126 filterPacket->OnCompletion(filterPacket->CompletionContext);
1127
1128 DPRINT_EXIT(NETVSC);
1129}
1130
1131
1132static void
1133RndisFilterOnSendRequestCompletion(
1134 void *Context
1135 )
1136{
1137 DPRINT_ENTER(NETVSC);
1138
Bill Pemberton454f18a2009-07-27 16:47:24 -04001139 /* Noop */
Hank Janssenfceaf242009-07-13 15:34:54 -07001140 DPRINT_EXIT(NETVSC);
1141}