win-pvdrivers

view xennet/xennet.c @ 387:48df739c66d4

Removed some debugging calls to the HLT instruction
author James Harper <james.harper@bendigoit.com.au>
date Fri Jul 11 14:05:34 2008 +1000 (2008-07-11)
parents d76831a77d19
children 8e10579159a0
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 /* ----- BEGIN Other people's code --------- */
26 /* from linux/include/linux/ctype.h, used under GPLv2 */
27 #define _U 0x01 /* upper */
28 #define _L 0x02 /* lower */
29 #define _D 0x04 /* digit */
30 #define _C 0x08 /* cntrl */
31 #define _P 0x10 /* punct */
32 #define _S 0x20 /* white space (space/lf/tab) */
33 #define _X 0x40 /* hex digit */
34 #define _SP 0x80 /* hard space (0x20) */
36 /* from linux/include/lib/ctype.c, used under GPLv2 */
37 unsigned char _ctype[] = {
38 _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
39 _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
40 _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
41 _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
42 _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
43 _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
44 _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
45 _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
46 _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
47 _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
48 _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
49 _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
50 _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
51 _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
52 _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
53 _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
54 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
55 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
56 _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
57 _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
58 _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
59 _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
60 _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
61 _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
63 /* from linux/include/linux/ctype.h, used under GPLv2 */
64 #define __ismask(x) (_ctype[(int)(unsigned char)(x)])
66 #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
67 #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
68 #define iscntrl(c) ((__ismask(c)&(_C)) != 0)
69 #define isdigit(c) ((__ismask(c)&(_D)) != 0)
70 #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
71 #define islower(c) ((__ismask(c)&(_L)) != 0)
72 #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
73 #define ispunct(c) ((__ismask(c)&(_P)) != 0)
74 #define isspace(c) ((__ismask(c)&(_S)) != 0)
75 #define isupper(c) ((__ismask(c)&(_U)) != 0)
76 #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
78 #define TOLOWER(x) ((x) | 0x20)
80 /* from linux/lib/vsprintf.c, used under GPLv2 */
81 /* Copyright (C) 1991, 1992 Linus Torvalds
82 * Wirzenius wrote this portably, Torvalds fucked it up :-)
83 */
84 /**
85 * simple_strtoul - convert a string to an unsigned long
86 * @cp: The start of the string
87 * @endp: A pointer to the end of the parsed string will be placed here
88 * @base: The number base to use
89 */
90 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
91 {
92 unsigned long result = 0,value;
94 if (!base) {
95 base = 10;
96 if (*cp == '0') {
97 base = 8;
98 cp++;
99 if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
100 cp++;
101 base = 16;
102 }
103 }
104 } else if (base == 16) {
105 if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
106 cp += 2;
107 }
108 while (isxdigit(*cp) &&
109 (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
110 result = result*base + value;
111 cp++;
112 }
113 if (endp)
114 *endp = (char *)cp;
115 return result;
116 }
117 /* end vsprintf.c code */
118 /* ----- END Other people's code --------- */
120 // Called at DISPATCH_LEVEL
122 static DDKAPI VOID
123 XenNet_InterruptIsr(
124 PBOOLEAN InterruptRecognized,
125 PBOOLEAN QueueMiniportHandleInterrupt,
126 NDIS_HANDLE MiniportAdapterContext)
127 {
128 struct xennet_info *xi = MiniportAdapterContext;
130 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
132 *QueueMiniportHandleInterrupt = (BOOLEAN)!!xi->connected;
133 *InterruptRecognized = FALSE; /* we can't be sure here... */
135 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
136 }
138 static DDKAPI VOID
139 XenNet_InterruptDpc(NDIS_HANDLE MiniportAdapterContext)
140 {
141 struct xennet_info *xi = MiniportAdapterContext;
143 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
144 if (xi->connected)
145 {
146 XenNet_TxBufferGC(xi);
147 XenNet_RxBufferCheck(xi);
148 }
149 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
150 }
152 static NDIS_STATUS
153 XenNet_ConnectBackend(struct xennet_info *xi)
154 {
155 PUCHAR ptr;
156 UCHAR type;
157 PCHAR setting, value;
158 UINT i;
160 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
162 ptr = xi->config_page;
163 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
164 {
165 switch(type)
166 {
167 case XEN_INIT_TYPE_RING: /* frontend ring */
168 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
169 if (strcmp(setting, "tx-ring-ref") == 0)
170 {
171 FRONT_RING_INIT(&xi->tx, (netif_tx_sring_t *)value, PAGE_SIZE);
172 } else if (strcmp(setting, "rx-ring-ref") == 0)
173 {
174 FRONT_RING_INIT(&xi->rx, (netif_rx_sring_t *)value, PAGE_SIZE);
175 }
176 break;
177 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
178 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
179 if (strcmp(setting, "event-channel") == 0)
180 {
181 xi->event_channel = PtrToUlong(value);
182 }
183 break;
184 case XEN_INIT_TYPE_READ_STRING_BACK:
185 case XEN_INIT_TYPE_READ_STRING_FRONT:
186 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
187 if (strcmp(setting, "mac") == 0)
188 {
189 char *s, *e;
190 s = value;
191 for (i = 0; i < ETH_ALEN; i++) {
192 xi->perm_mac_addr[i] = (uint8_t)simple_strtoul(s, &e, 16);
193 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
194 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
195 }
196 s = e + 1;
197 }
198 memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
199 }
200 break;
201 case XEN_INIT_TYPE_VECTORS:
202 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
203 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
204 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
205 {
206 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
207 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
208 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
209 return NDIS_STATUS_ADAPTER_NOT_FOUND;
210 }
211 else
212 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
213 break;
214 case XEN_INIT_TYPE_STATE_PTR:
215 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
216 xi->device_state = (PXENPCI_DEVICE_STATE)value;
217 break;
218 default:
219 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
220 break;
221 }
222 }
223 return NDIS_STATUS_SUCCESS;
224 }
226 static DDKAPI VOID
227 XenNet_Resume(PDEVICE_OBJECT device_object, PVOID context)
228 {
229 struct xennet_info *xi = context;
231 UNREFERENCED_PARAMETER(device_object);
233 XenNet_RxResumeStart(xi);
234 XenNet_TxResumeStart(xi);
235 XenNet_ConnectBackend(xi);
236 xi->device_state->resume_state = RESUME_STATE_RUNNING;
237 XenNet_RxResumeEnd(xi);
238 XenNet_TxResumeEnd(xi);
239 NdisMSetPeriodicTimer(&xi->resume_timer, 100);
240 }
242 static DDKAPI VOID
243 XenResumeCheck_Timer(
244 PVOID SystemSpecific1,
245 PVOID FunctionContext,
246 PVOID SystemSpecific2,
247 PVOID SystemSpecific3
248 )
249 {
250 struct xennet_info *xi = FunctionContext;
251 PIO_WORKITEM work_item;
252 BOOLEAN timer_cancelled;
254 UNREFERENCED_PARAMETER(SystemSpecific1);
255 UNREFERENCED_PARAMETER(SystemSpecific2);
256 UNREFERENCED_PARAMETER(SystemSpecific3);
258 if (xi->device_state->resume_state == RESUME_STATE_FRONTEND_RESUME)
259 {
260 NdisMCancelTimer(&xi->resume_timer, &timer_cancelled);
261 work_item = IoAllocateWorkItem(xi->fdo);
262 IoQueueWorkItem(work_item, XenNet_Resume, DelayedWorkQueue, xi);
263 }
264 }
266 // Called at <= DISPATCH_LEVEL
267 static DDKAPI NDIS_STATUS
268 XenNet_Init(
269 OUT PNDIS_STATUS OpenErrorStatus,
270 OUT PUINT SelectedMediumIndex,
271 IN PNDIS_MEDIUM MediumArray,
272 IN UINT MediumArraySize,
273 IN NDIS_HANDLE MiniportAdapterHandle,
274 IN NDIS_HANDLE WrapperConfigurationContext
275 )
276 {
277 NDIS_STATUS status;
278 BOOLEAN medium_found = FALSE;
279 struct xennet_info *xi = NULL;
280 ULONG nrl_length;
281 PNDIS_RESOURCE_LIST nrl;
282 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
283 KIRQL irq_level = 0;
284 ULONG irq_vector = 0;
285 NDIS_HANDLE config_handle;
286 NDIS_STRING config_param_name;
287 PNDIS_CONFIGURATION_PARAMETER config_param;
288 ULONG i;
289 PUCHAR ptr;
290 UCHAR type;
291 PCHAR setting, value;
292 ULONG length;
293 CHAR buf[128];
295 UNREFERENCED_PARAMETER(OpenErrorStatus);
297 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
298 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
300 /* deal with medium stuff */
301 for (i = 0; i < MediumArraySize; i++)
302 {
303 if (MediumArray[i] == NdisMedium802_3)
304 {
305 medium_found = TRUE;
306 break;
307 }
308 }
309 if (!medium_found)
310 {
311 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
312 return NDIS_STATUS_UNSUPPORTED_MEDIA;
313 }
314 *SelectedMediumIndex = i;
316 /* Alloc memory for adapter private info */
317 status = NdisAllocateMemoryWithTag((PVOID)&xi, sizeof(*xi), XENNET_POOL_TAG);
318 if (!NT_SUCCESS(status))
319 {
320 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
321 status = NDIS_STATUS_RESOURCES;
322 goto err;
323 }
324 RtlZeroMemory(xi, sizeof(*xi));
325 xi->adapter_handle = MiniportAdapterHandle;
326 xi->rx_target = RX_DFL_MIN_TARGET;
327 xi->rx_min_target = RX_DFL_MIN_TARGET;
328 xi->rx_max_target = RX_MAX_TARGET;
329 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
330 0, NDIS_ATTRIBUTE_DESERIALIZE, // | NDIS_ATTRIBUTE_BUS_MASTER),
331 NdisInterfaceInternal);
333 nrl_length = 0;
334 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
335 NULL, (PUINT)&nrl_length);
336 KdPrint((__DRIVER_NAME " nrl_length = %d\n", nrl_length));
337 status = NdisAllocateMemoryWithTag((PVOID)&nrl, nrl_length, XENNET_POOL_TAG);
338 if (status != NDIS_STATUS_SUCCESS)
339 {
340 KdPrint((__DRIVER_NAME " Could not get allocate memory for Adapter Resources 0x%x\n", status));
341 return NDIS_STATUS_RESOURCES;
342 }
343 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
344 nrl, (PUINT)&nrl_length);
345 if (status != NDIS_STATUS_SUCCESS)
346 {
347 KdPrint((__DRIVER_NAME " Could not get Adapter Resources 0x%x\n", status));
348 return NDIS_STATUS_RESOURCES;
349 }
350 xi->event_channel = 0;
351 xi->config_csum = 1;
352 xi->config_sg = 1;
353 xi->config_gso = 61440;
354 xi->config_page = NULL;
356 for (i = 0; i < nrl->Count; i++)
357 {
358 prd = &nrl->PartialDescriptors[i];
360 switch(prd->Type)
361 {
362 case CmResourceTypeInterrupt:
363 irq_vector = prd->u.Interrupt.Vector;
364 irq_level = (KIRQL)prd->u.Interrupt.Level;
365 KdPrint((__DRIVER_NAME " irq_vector = %03x, irq_level = %03x\n", irq_vector, irq_level));
366 break;
368 case CmResourceTypeMemory:
369 status = NdisMMapIoSpace(&xi->config_page, MiniportAdapterHandle, prd->u.Memory.Start, prd->u.Memory.Length);
370 if (!NT_SUCCESS(status))
371 {
372 KdPrint(("NdisMMapIoSpace failed with 0x%x\n", status));
373 NdisFreeMemory(nrl, nrl_length, 0);
374 return NDIS_STATUS_RESOURCES;
375 }
376 break;
377 }
378 }
379 NdisFreeMemory(nrl, nrl_length, 0);
380 if (!xi->config_page)
381 {
382 KdPrint(("No config page given\n"));
383 return NDIS_STATUS_RESOURCES;
384 }
386 KeInitializeSpinLock(&xi->rx_lock);
388 InitializeListHead(&xi->tx_waiting_pkt_list);
390 NdisAllocatePacketPool(&status, &xi->packet_pool, XN_RX_QUEUE_LEN * 8,
391 PROTOCOL_RESERVED_SIZE_IN_PACKET);
392 if (status != NDIS_STATUS_SUCCESS)
393 {
394 KdPrint(("NdisAllocatePacketPool failed with 0x%x\n", status));
395 status = NDIS_STATUS_RESOURCES;
396 goto err;
397 }
398 NdisSetPacketPoolProtocolId(xi->packet_pool, NDIS_PROTOCOL_ID_TCP_IP);
400 NdisAllocateBufferPool(&status, &xi->buffer_pool, XN_RX_QUEUE_LEN);
401 if (status != NDIS_STATUS_SUCCESS)
402 {
403 KdPrint(("NdisAllocateBufferPool failed with 0x%x\n", status));
404 status = NDIS_STATUS_RESOURCES;
405 goto err;
406 }
408 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
409 &xi->lower_do, NULL, NULL);
410 xi->packet_filter = NDIS_PACKET_TYPE_PROMISCUOUS;
412 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
413 NAME_SIZE, xi->dev_desc, &length);
414 if (!NT_SUCCESS(status))
415 {
416 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
417 status = NDIS_STATUS_FAILURE;
418 goto err;
419 }
421 ptr = xi->config_page;
422 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
423 {
424 switch(type)
425 {
426 case XEN_INIT_TYPE_VECTORS:
427 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
428 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
429 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
430 {
431 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
432 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
433 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
434 return NDIS_STATUS_FAILURE;
435 }
436 else
437 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
438 break;
439 case XEN_INIT_TYPE_STATE_PTR:
440 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
441 xi->device_state = (PXENPCI_DEVICE_STATE)value;
442 break;
443 default:
444 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
445 break;
446 }
447 }
449 // now build config page
451 NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
452 if (!NT_SUCCESS(status))
453 {
454 KdPrint(("Could not open config in registry (%08x)\n", status));
455 goto err;
456 }
458 NdisInitUnicodeString(&config_param_name, L"ScatterGather");
459 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
460 if (!NT_SUCCESS(status))
461 {
462 KdPrint(("Could not read ScatterGather value (%08x)\n", status));
463 xi->config_sg = 1;
464 }
465 else
466 {
467 KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData));
468 xi->config_sg = config_param->ParameterData.IntegerData;
469 }
471 NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
472 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
473 if (!NT_SUCCESS(status))
474 {
475 KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
476 xi->config_gso = 0;
477 }
478 else
479 {
480 KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
481 xi->config_gso = config_param->ParameterData.IntegerData;
482 if (xi->config_gso > 61440)
483 {
484 xi->config_gso = 61440;
485 KdPrint(("(clipped to %d)\n", xi->config_gso));
486 }
487 }
489 NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
490 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
491 if (!NT_SUCCESS(status))
492 {
493 KdPrint(("Could not read ChecksumOffload value (%08x)\n", status));
494 xi->config_csum = 1;
495 }
496 else
497 {
498 KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData));
499 xi->config_csum = !!config_param->ParameterData.IntegerData;
500 }
502 NdisInitUnicodeString(&config_param_name, L"MTU");
503 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
504 if (!NT_SUCCESS(status))
505 {
506 KdPrint(("Could not read MTU value (%08x)\n", status));
507 xi->config_mtu = 1500;
508 }
509 else
510 {
511 KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData));
512 xi->config_mtu = config_param->ParameterData.IntegerData;
513 }
515 xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE);
517 NdisCloseConfiguration(config_handle);
519 ptr = xi->config_page;
520 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL);
521 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL);
522 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL);
523 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
524 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mac", NULL);
525 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
526 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf);
527 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->config_sg);
528 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf);
529 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
530 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf);
531 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1");
532 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1");
533 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
535 status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
536 // check return value
538 status = XenNet_ConnectBackend(xi);
540 KeInitializeEvent(&xi->shutdown_event, SynchronizationEvent, FALSE);
542 XenNet_TxInit(xi);
543 XenNet_RxInit(xi);
545 xi->connected = TRUE;
547 KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
549 status = NdisMRegisterInterrupt(&xi->interrupt, MiniportAdapterHandle, irq_vector, irq_level,
550 TRUE, TRUE, NdisInterruptLatched);
551 /* send fake arp? */
552 if (!NT_SUCCESS(status))
553 {
554 KdPrint(("NdisMRegisterInterrupt failed with 0x%x\n", status));
555 //status = NDIS_STATUS_FAILURE;
556 //goto err;
557 }
559 NdisMInitializeTimer(&xi->resume_timer, xi->adapter_handle, XenResumeCheck_Timer, xi);
560 NdisMSetPeriodicTimer(&xi->resume_timer, 100);
562 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
564 return NDIS_STATUS_SUCCESS;
566 err:
567 NdisFreeMemory(xi, 0, 0);
568 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (error path)\n"));
569 return status;
570 }
572 VOID
573 XenNet_PnPEventNotify(
574 IN NDIS_HANDLE MiniportAdapterContext,
575 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
576 IN PVOID InformationBuffer,
577 IN ULONG InformationBufferLength
578 )
579 {
580 UNREFERENCED_PARAMETER(MiniportAdapterContext);
581 UNREFERENCED_PARAMETER(PnPEvent);
582 UNREFERENCED_PARAMETER(InformationBuffer);
583 UNREFERENCED_PARAMETER(InformationBufferLength);
585 KdPrint((__FUNCTION__ " called\n"));
586 }
588 /* Called when machine is shutting down, so just quiesce the HW and be done fast. */
589 VOID DDKAPI
590 XenNet_Shutdown(
591 IN NDIS_HANDLE MiniportAdapterContext
592 )
593 {
594 struct xennet_info *xi = MiniportAdapterContext;
596 KdPrint((__FUNCTION__ " called\n"));
598 NdisMDeregisterInterrupt(&xi->interrupt);
599 }
601 /* Opposite of XenNet_Init */
602 VOID DDKAPI
603 XenNet_Halt(
604 IN NDIS_HANDLE MiniportAdapterContext
605 )
606 {
607 struct xennet_info *xi = MiniportAdapterContext;
608 // CHAR TmpPath[MAX_XENBUS_STR_LEN];
609 // PVOID if_cxt = xi->XenInterface.InterfaceHeader.Context;
610 // LARGE_INTEGER timeout;
612 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
613 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
615 // Disables the interrupt
616 XenNet_Shutdown(xi);
618 xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
620 xi->connected = FALSE;
621 KeMemoryBarrier(); /* make sure everyone sees that we are now shut down */
623 // TODO: remove event channel xenbus entry (how?)
625 XenNet_TxShutdown(xi);
626 XenNet_RxShutdown(xi);
628 NdisFreeBufferPool(xi->buffer_pool);
629 NdisFreePacketPool(xi->packet_pool);
631 NdisFreeMemory(xi, 0, 0); // <= DISPATCH_LEVEL
633 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
634 }
636 NTSTATUS
637 DriverEntry(
638 PDRIVER_OBJECT DriverObject,
639 PUNICODE_STRING RegistryPath
640 )
641 {
642 NTSTATUS status;
643 NDIS_HANDLE ndis_wrapper_handle;
644 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
646 RtlZeroMemory(&mini_chars, sizeof(mini_chars));
648 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
649 if (!ndis_wrapper_handle)
650 {
651 KdPrint(("NdisMInitializeWrapper failed\n"));
652 return NDIS_STATUS_FAILURE;
653 }
655 /* NDIS 5.1 driver */
656 mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
657 mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
659 mini_chars.HaltHandler = XenNet_Halt;
660 mini_chars.InitializeHandler = XenNet_Init;
661 mini_chars.ISRHandler = XenNet_InterruptIsr;
662 mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
663 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
664 mini_chars.ResetHandler = NULL; //TODO: fill in
665 mini_chars.SetInformationHandler = XenNet_SetInformation;
666 /* added in v.4 -- use multiple pkts interface */
667 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
668 mini_chars.SendPacketsHandler = XenNet_SendPackets;
670 #if defined (NDIS51_MINIPORT)
671 /* added in v.5.1 */
672 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
673 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
674 #else
675 // something else here
676 #endif
678 /* set up upper-edge interface */
679 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
680 if (!NT_SUCCESS(status))
681 {
682 KdPrint(("NdisMRegisterMiniport failed, status = 0x%x\n", status));
683 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
684 return status;
685 }
687 return status;
688 }