win-pvdrivers

view xennet/xennet.c @ 369:5a762fd1fba9

build xennet using mingw
author Andy Grover <andy.grover@oracle.com>
date Wed Jul 09 00:20:30 2008 -0700 (2008-07-09)
parents a7c4b65e754a
children d76831a77d19
line source
1 /*
2 PV Net Driver for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
4 Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
21 #include <stdlib.h>
22 #include <io/xenbus.h>
23 #include "xennet.h"
25 LARGE_INTEGER ProfTime_TxBufferGC;
26 LARGE_INTEGER ProfTime_RxBufferAlloc;
27 LARGE_INTEGER ProfTime_ReturnPacket;
28 LARGE_INTEGER ProfTime_RxBufferCheck;
29 LARGE_INTEGER ProfTime_Linearize;
30 LARGE_INTEGER ProfTime_SendPackets;
31 LARGE_INTEGER ProfTime_SendQueuedPackets;
32 LARGE_INTEGER ProfTime_RxBufferCheckTopHalf;
33 LARGE_INTEGER ProfTime_RxBufferCheckBotHalf;
35 int ProfCount_TxBufferGC;
36 int ProfCount_RxBufferAlloc;
37 int ProfCount_ReturnPacket;
38 int ProfCount_RxBufferCheck;
39 int ProfCount_Linearize;
40 int ProfCount_SendPackets;
41 int ProfCount_PacketsPerSendPackets;
42 int ProfCount_SendQueuedPackets;
44 int ProfCount_TxPacketsTotal;
45 int ProfCount_TxPacketsCsumOffload;
46 int ProfCount_TxPacketsLargeOffload;
47 int ProfCount_RxPacketsTotal;
48 int ProfCount_RxPacketsCsumOffload;
49 int ProfCount_CallsToIndicateReceive;
51 /* ----- BEGIN Other people's code --------- */
52 /* from linux/include/linux/ctype.h, used under GPLv2 */
53 #define _U 0x01 /* upper */
54 #define _L 0x02 /* lower */
55 #define _D 0x04 /* digit */
56 #define _C 0x08 /* cntrl */
57 #define _P 0x10 /* punct */
58 #define _S 0x20 /* white space (space/lf/tab) */
59 #define _X 0x40 /* hex digit */
60 #define _SP 0x80 /* hard space (0x20) */
62 /* from linux/include/lib/ctype.c, used under GPLv2 */
63 unsigned char _ctype[] = {
64 _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
65 _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
66 _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
67 _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
68 _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
69 _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
70 _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
71 _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
72 _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
73 _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
74 _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
75 _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
76 _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
77 _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
78 _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
79 _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
80 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
81 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
82 _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
83 _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
84 _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
85 _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
86 _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
87 _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
89 /* from linux/include/linux/ctype.h, used under GPLv2 */
90 #define __ismask(x) (_ctype[(int)(unsigned char)(x)])
92 #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
93 #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
94 #define iscntrl(c) ((__ismask(c)&(_C)) != 0)
95 #define isdigit(c) ((__ismask(c)&(_D)) != 0)
96 #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
97 #define islower(c) ((__ismask(c)&(_L)) != 0)
98 #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
99 #define ispunct(c) ((__ismask(c)&(_P)) != 0)
100 #define isspace(c) ((__ismask(c)&(_S)) != 0)
101 #define isupper(c) ((__ismask(c)&(_U)) != 0)
102 #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
104 #define TOLOWER(x) ((x) | 0x20)
106 /* from linux/lib/vsprintf.c, used under GPLv2 */
107 /* Copyright (C) 1991, 1992 Linus Torvalds
108 * Wirzenius wrote this portably, Torvalds fucked it up :-)
109 */
110 /**
111 * simple_strtoul - convert a string to an unsigned long
112 * @cp: The start of the string
113 * @endp: A pointer to the end of the parsed string will be placed here
114 * @base: The number base to use
115 */
116 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
117 {
118 unsigned long result = 0,value;
120 if (!base) {
121 base = 10;
122 if (*cp == '0') {
123 base = 8;
124 cp++;
125 if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
126 cp++;
127 base = 16;
128 }
129 }
130 } else if (base == 16) {
131 if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
132 cp += 2;
133 }
134 while (isxdigit(*cp) &&
135 (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
136 result = result*base + value;
137 cp++;
138 }
139 if (endp)
140 *endp = (char *)cp;
141 return result;
142 }
143 /* end vsprintf.c code */
144 /* ----- END Other people's code --------- */
146 // Called at DISPATCH_LEVEL
148 static DDKAPI VOID
149 XenNet_InterruptIsr(
150 PBOOLEAN InterruptRecognized,
151 PBOOLEAN QueueMiniportHandleInterrupt,
152 NDIS_HANDLE MiniportAdapterContext)
153 {
154 struct xennet_info *xi = MiniportAdapterContext;
156 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
158 *QueueMiniportHandleInterrupt = (BOOLEAN)!!xi->connected;
159 *InterruptRecognized = FALSE; /* we can't be sure here... */
161 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
162 }
164 static DDKAPI VOID
165 XenNet_InterruptDpc(NDIS_HANDLE MiniportAdapterContext)
166 {
167 struct xennet_info *xi = MiniportAdapterContext;
169 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
170 if (xi->connected)
171 {
172 XenNet_TxBufferGC(xi);
173 XenNet_RxBufferCheck(xi);
174 }
175 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
176 }
178 static NDIS_STATUS
179 XenNet_ConnectBackend(struct xennet_info *xi)
180 {
181 PUCHAR ptr;
182 UCHAR type;
183 PCHAR setting, value;
184 UINT i;
186 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
188 ptr = xi->config_page;
189 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
190 {
191 switch(type)
192 {
193 case XEN_INIT_TYPE_RING: /* frontend ring */
194 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
195 if (strcmp(setting, "tx-ring-ref") == 0)
196 {
197 FRONT_RING_INIT(&xi->tx, (netif_tx_sring_t *)value, PAGE_SIZE);
198 } else if (strcmp(setting, "rx-ring-ref") == 0)
199 {
200 FRONT_RING_INIT(&xi->rx, (netif_rx_sring_t *)value, PAGE_SIZE);
201 }
202 break;
203 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
204 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
205 if (strcmp(setting, "event-channel") == 0)
206 {
207 xi->event_channel = PtrToUlong(value);
208 }
209 break;
210 case XEN_INIT_TYPE_READ_STRING_BACK:
211 case XEN_INIT_TYPE_READ_STRING_FRONT:
212 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
213 if (strcmp(setting, "mac") == 0)
214 {
215 char *s, *e;
216 s = value;
217 for (i = 0; i < ETH_ALEN; i++) {
218 xi->perm_mac_addr[i] = (uint8_t)simple_strtoul(s, &e, 16);
219 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
220 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
221 }
222 s = e + 1;
223 }
224 memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
225 }
226 break;
227 case XEN_INIT_TYPE_VECTORS:
228 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
229 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
230 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
231 {
232 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
233 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
234 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
235 return NDIS_STATUS_ADAPTER_NOT_FOUND;
236 }
237 else
238 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
239 break;
240 case XEN_INIT_TYPE_STATE_PTR:
241 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
242 xi->device_state = (PXENPCI_DEVICE_STATE)value;
243 break;
244 default:
245 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
246 break;
247 }
248 }
249 return NDIS_STATUS_SUCCESS;
250 }
252 static DDKAPI VOID
253 XenNet_Resume(PDEVICE_OBJECT device_object, PVOID context)
254 {
255 struct xennet_info *xi = context;
257 UNREFERENCED_PARAMETER(device_object);
259 XenNet_RxResumeStart(xi);
260 XenNet_TxResumeStart(xi);
261 XenNet_ConnectBackend(xi);
262 xi->device_state->resume_state = RESUME_STATE_RUNNING;
263 XenNet_RxResumeEnd(xi);
264 XenNet_TxResumeEnd(xi);
265 NdisMSetPeriodicTimer(&xi->resume_timer, 100);
266 }
268 static DDKAPI VOID
269 XenResumeCheck_Timer(
270 PVOID SystemSpecific1,
271 PVOID FunctionContext,
272 PVOID SystemSpecific2,
273 PVOID SystemSpecific3
274 )
275 {
276 struct xennet_info *xi = FunctionContext;
277 PIO_WORKITEM work_item;
278 BOOLEAN timer_cancelled;
280 UNREFERENCED_PARAMETER(SystemSpecific1);
281 UNREFERENCED_PARAMETER(SystemSpecific2);
282 UNREFERENCED_PARAMETER(SystemSpecific3);
284 if (xi->device_state->resume_state == RESUME_STATE_FRONTEND_RESUME)
285 {
286 NdisMCancelTimer(&xi->resume_timer, &timer_cancelled);
287 work_item = IoAllocateWorkItem(xi->fdo);
288 IoQueueWorkItem(work_item, XenNet_Resume, DelayedWorkQueue, xi);
289 }
290 }
292 // Called at <= DISPATCH_LEVEL
293 static DDKAPI NDIS_STATUS
294 XenNet_Init(
295 OUT PNDIS_STATUS OpenErrorStatus,
296 OUT PUINT SelectedMediumIndex,
297 IN PNDIS_MEDIUM MediumArray,
298 IN UINT MediumArraySize,
299 IN NDIS_HANDLE MiniportAdapterHandle,
300 IN NDIS_HANDLE WrapperConfigurationContext
301 )
302 {
303 NDIS_STATUS status;
304 BOOLEAN medium_found = FALSE;
305 struct xennet_info *xi = NULL;
306 ULONG nrl_length;
307 PNDIS_RESOURCE_LIST nrl;
308 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
309 KIRQL irq_level = 0;
310 ULONG irq_vector = 0;
311 NDIS_HANDLE config_handle;
312 NDIS_STRING config_param_name;
313 PNDIS_CONFIGURATION_PARAMETER config_param;
314 ULONG i;
315 PUCHAR ptr;
316 UCHAR type;
317 PCHAR setting, value;
318 ULONG length;
319 CHAR buf[128];
321 UNREFERENCED_PARAMETER(OpenErrorStatus);
323 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
324 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
326 /* deal with medium stuff */
327 for (i = 0; i < MediumArraySize; i++)
328 {
329 if (MediumArray[i] == NdisMedium802_3)
330 {
331 medium_found = TRUE;
332 break;
333 }
334 }
335 if (!medium_found)
336 {
337 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
338 return NDIS_STATUS_UNSUPPORTED_MEDIA;
339 }
340 *SelectedMediumIndex = i;
342 /* Alloc memory for adapter private info */
343 status = NdisAllocateMemoryWithTag((PVOID)&xi, sizeof(*xi), XENNET_POOL_TAG);
344 if (!NT_SUCCESS(status))
345 {
346 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
347 status = NDIS_STATUS_RESOURCES;
348 goto err;
349 }
350 RtlZeroMemory(xi, sizeof(*xi));
351 xi->adapter_handle = MiniportAdapterHandle;
352 xi->rx_target = RX_DFL_MIN_TARGET;
353 xi->rx_min_target = RX_DFL_MIN_TARGET;
354 xi->rx_max_target = RX_MAX_TARGET;
355 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
356 0, NDIS_ATTRIBUTE_DESERIALIZE, // | NDIS_ATTRIBUTE_BUS_MASTER),
357 NdisInterfaceInternal);
359 nrl_length = 0;
360 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
361 NULL, (PUINT)&nrl_length);
362 KdPrint((__DRIVER_NAME " nrl_length = %d\n", nrl_length));
363 status = NdisAllocateMemoryWithTag((PVOID)&nrl, nrl_length, XENNET_POOL_TAG);
364 if (status != NDIS_STATUS_SUCCESS)
365 {
366 KdPrint((__DRIVER_NAME " Could not get allocate memory for Adapter Resources 0x%x\n", status));
367 return NDIS_STATUS_RESOURCES;
368 }
369 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
370 nrl, (PUINT)&nrl_length);
371 if (status != NDIS_STATUS_SUCCESS)
372 {
373 KdPrint((__DRIVER_NAME " Could not get Adapter Resources 0x%x\n", status));
374 return NDIS_STATUS_RESOURCES;
375 }
376 xi->event_channel = 0;
377 xi->config_csum = 1;
378 xi->config_sg = 1;
379 xi->config_gso = 61440;
380 xi->config_page = NULL;
382 for (i = 0; i < nrl->Count; i++)
383 {
384 prd = &nrl->PartialDescriptors[i];
386 switch(prd->Type)
387 {
388 case CmResourceTypeInterrupt:
389 irq_vector = prd->u.Interrupt.Vector;
390 irq_level = (KIRQL)prd->u.Interrupt.Level;
391 KdPrint((__DRIVER_NAME " irq_vector = %03x, irq_level = %03x\n", irq_vector, irq_level));
392 break;
394 case CmResourceTypeMemory:
395 status = NdisMMapIoSpace(&xi->config_page, MiniportAdapterHandle, prd->u.Memory.Start, prd->u.Memory.Length);
396 if (!NT_SUCCESS(status))
397 {
398 KdPrint(("NdisMMapIoSpace failed with 0x%x\n", status));
399 NdisFreeMemory(nrl, nrl_length, 0);
400 return NDIS_STATUS_RESOURCES;
401 }
402 break;
403 }
404 }
405 NdisFreeMemory(nrl, nrl_length, 0);
406 if (!xi->config_page)
407 {
408 KdPrint(("No config page given\n"));
409 return NDIS_STATUS_RESOURCES;
410 }
412 KeInitializeSpinLock(&xi->rx_lock);
414 InitializeListHead(&xi->tx_waiting_pkt_list);
416 NdisAllocatePacketPool(&status, &xi->packet_pool, XN_RX_QUEUE_LEN * 8,
417 PROTOCOL_RESERVED_SIZE_IN_PACKET);
418 if (status != NDIS_STATUS_SUCCESS)
419 {
420 KdPrint(("NdisAllocatePacketPool failed with 0x%x\n", status));
421 status = NDIS_STATUS_RESOURCES;
422 goto err;
423 }
424 NdisSetPacketPoolProtocolId(xi->packet_pool, NDIS_PROTOCOL_ID_TCP_IP);
426 NdisAllocateBufferPool(&status, &xi->buffer_pool, XN_RX_QUEUE_LEN);
427 if (status != NDIS_STATUS_SUCCESS)
428 {
429 KdPrint(("NdisAllocateBufferPool failed with 0x%x\n", status));
430 status = NDIS_STATUS_RESOURCES;
431 goto err;
432 }
434 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
435 &xi->lower_do, NULL, NULL);
436 xi->packet_filter = NDIS_PACKET_TYPE_PROMISCUOUS;
438 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
439 NAME_SIZE, xi->dev_desc, &length);
440 if (!NT_SUCCESS(status))
441 {
442 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
443 status = NDIS_STATUS_FAILURE;
444 goto err;
445 }
447 ptr = xi->config_page;
448 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
449 {
450 switch(type)
451 {
452 case XEN_INIT_TYPE_VECTORS:
453 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
454 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
455 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
456 {
457 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
458 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
459 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
460 return NDIS_STATUS_FAILURE;
461 }
462 else
463 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
464 break;
465 case XEN_INIT_TYPE_STATE_PTR:
466 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
467 xi->device_state = (PXENPCI_DEVICE_STATE)value;
468 break;
469 default:
470 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
471 break;
472 }
473 }
475 // now build config page
477 NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
478 if (!NT_SUCCESS(status))
479 {
480 KdPrint(("Could not open config in registry (%08x)\n", status));
481 goto err;
482 }
484 NdisInitUnicodeString(&config_param_name, L"ScatterGather");
485 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
486 if (!NT_SUCCESS(status))
487 {
488 KdPrint(("Could not read ScatterGather value (%08x)\n", status));
489 xi->config_sg = 1;
490 }
491 else
492 {
493 KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData));
494 xi->config_sg = config_param->ParameterData.IntegerData;
495 }
497 NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
498 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
499 if (!NT_SUCCESS(status))
500 {
501 KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
502 xi->config_gso = 0;
503 }
504 else
505 {
506 KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
507 xi->config_gso = config_param->ParameterData.IntegerData;
508 if (xi->config_gso > 61440)
509 {
510 xi->config_gso = 61440;
511 KdPrint(("(clipped to %d)\n", xi->config_gso));
512 }
513 }
515 NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
516 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
517 if (!NT_SUCCESS(status))
518 {
519 KdPrint(("Could not read ChecksumOffload value (%08x)\n", status));
520 xi->config_csum = 1;
521 }
522 else
523 {
524 KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData));
525 xi->config_csum = !!config_param->ParameterData.IntegerData;
526 }
528 NdisInitUnicodeString(&config_param_name, L"MTU");
529 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
530 if (!NT_SUCCESS(status))
531 {
532 KdPrint(("Could not read MTU value (%08x)\n", status));
533 xi->config_mtu = 1500;
534 }
535 else
536 {
537 KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData));
538 xi->config_mtu = config_param->ParameterData.IntegerData;
539 }
541 xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE);
543 NdisCloseConfiguration(config_handle);
545 ptr = xi->config_page;
546 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL);
547 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL);
548 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL);
549 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
550 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mac", NULL);
551 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
552 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf);
553 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->config_sg);
554 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf);
555 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
556 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf);
557 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1");
558 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1");
559 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
561 status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
562 // check return value
564 status = XenNet_ConnectBackend(xi);
566 KeInitializeEvent(&xi->shutdown_event, SynchronizationEvent, FALSE);
568 XenNet_TxInit(xi);
569 XenNet_RxInit(xi);
571 xi->connected = TRUE;
573 KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
575 status = NdisMRegisterInterrupt(&xi->interrupt, MiniportAdapterHandle, irq_vector, irq_level,
576 TRUE, TRUE, NdisInterruptLatched);
577 /* send fake arp? */
578 if (!NT_SUCCESS(status))
579 {
580 KdPrint(("NdisMRegisterInterrupt failed with 0x%x\n", status));
581 //status = NDIS_STATUS_FAILURE;
582 //goto err;
583 }
585 NdisMInitializeTimer(&xi->resume_timer, xi->adapter_handle, XenResumeCheck_Timer, xi);
586 NdisMSetPeriodicTimer(&xi->resume_timer, 100);
588 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
590 return NDIS_STATUS_SUCCESS;
592 err:
593 NdisFreeMemory(xi, 0, 0);
594 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (error path)\n"));
595 return status;
596 }
598 VOID
599 XenNet_PnPEventNotify(
600 IN NDIS_HANDLE MiniportAdapterContext,
601 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
602 IN PVOID InformationBuffer,
603 IN ULONG InformationBufferLength
604 )
605 {
606 UNREFERENCED_PARAMETER(MiniportAdapterContext);
607 UNREFERENCED_PARAMETER(PnPEvent);
608 UNREFERENCED_PARAMETER(InformationBuffer);
609 UNREFERENCED_PARAMETER(InformationBufferLength);
611 KdPrint((__FUNCTION__ " called\n"));
612 }
614 /* Called when machine is shutting down, so just quiesce the HW and be done fast. */
615 VOID DDKAPI
616 XenNet_Shutdown(
617 IN NDIS_HANDLE MiniportAdapterContext
618 )
619 {
620 struct xennet_info *xi = MiniportAdapterContext;
622 KdPrint((__FUNCTION__ " called\n"));
624 NdisMDeregisterInterrupt(&xi->interrupt);
625 }
627 /* Opposite of XenNet_Init */
628 VOID DDKAPI
629 XenNet_Halt(
630 IN NDIS_HANDLE MiniportAdapterContext
631 )
632 {
633 struct xennet_info *xi = MiniportAdapterContext;
634 // CHAR TmpPath[MAX_XENBUS_STR_LEN];
635 // PVOID if_cxt = xi->XenInterface.InterfaceHeader.Context;
636 // LARGE_INTEGER timeout;
638 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
639 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
641 // Disables the interrupt
642 XenNet_Shutdown(xi);
644 xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
646 xi->connected = FALSE;
647 KeMemoryBarrier(); /* make sure everyone sees that we are now shut down */
649 // TODO: remove event channel xenbus entry (how?)
651 XenNet_TxShutdown(xi);
652 XenNet_RxShutdown(xi);
654 NdisFreeBufferPool(xi->buffer_pool);
655 NdisFreePacketPool(xi->packet_pool);
657 NdisFreeMemory(xi, 0, 0); // <= DISPATCH_LEVEL
659 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
660 }
662 NTSTATUS
663 DriverEntry(
664 PDRIVER_OBJECT DriverObject,
665 PUNICODE_STRING RegistryPath
666 )
667 {
668 NTSTATUS status;
669 NDIS_HANDLE ndis_wrapper_handle;
670 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
672 ProfTime_TxBufferGC.QuadPart = 0;
673 ProfTime_RxBufferAlloc.QuadPart = 0;
674 ProfTime_ReturnPacket.QuadPart = 0;
675 ProfTime_RxBufferCheck.QuadPart = 0;
676 ProfTime_RxBufferCheckTopHalf.QuadPart = 0;
677 ProfTime_RxBufferCheckBotHalf.QuadPart = 0;
678 ProfTime_Linearize.QuadPart = 0;
679 ProfTime_SendPackets.QuadPart = 0;
680 ProfTime_SendQueuedPackets.QuadPart = 0;
682 ProfCount_TxBufferGC = 0;
683 ProfCount_RxBufferAlloc = 0;
684 ProfCount_ReturnPacket = 0;
685 ProfCount_RxBufferCheck = 0;
686 ProfCount_Linearize = 0;
687 ProfCount_SendPackets = 0;
688 ProfCount_PacketsPerSendPackets = 0;
689 ProfCount_SendQueuedPackets = 0;
691 ProfCount_TxPacketsTotal = 0;
692 ProfCount_TxPacketsCsumOffload = 0;
693 ProfCount_TxPacketsLargeOffload = 0;
694 ProfCount_RxPacketsTotal = 0;
695 ProfCount_RxPacketsCsumOffload = 0;
696 ProfCount_CallsToIndicateReceive = 0;
698 RtlZeroMemory(&mini_chars, sizeof(mini_chars));
700 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
701 if (!ndis_wrapper_handle)
702 {
703 KdPrint(("NdisMInitializeWrapper failed\n"));
704 return NDIS_STATUS_FAILURE;
705 }
707 /* NDIS 5.1 driver */
708 mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
709 mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
711 mini_chars.HaltHandler = XenNet_Halt;
712 mini_chars.InitializeHandler = XenNet_Init;
713 mini_chars.ISRHandler = XenNet_InterruptIsr;
714 mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
715 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
716 mini_chars.ResetHandler = NULL; //TODO: fill in
717 mini_chars.SetInformationHandler = XenNet_SetInformation;
718 /* added in v.4 -- use multiple pkts interface */
719 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
720 mini_chars.SendPacketsHandler = XenNet_SendPackets;
722 #if defined (NDIS51_MINIPORT)
723 /* added in v.5.1 */
724 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
725 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
726 #else
727 // something else here
728 #endif
730 /* set up upper-edge interface */
731 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
732 if (!NT_SUCCESS(status))
733 {
734 KdPrint(("NdisMRegisterMiniport failed, status = 0x%x\n", status));
735 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
736 return status;
737 }
739 return status;
740 }